69 const int QHttpNetworkConnectionPrivate::defaultChannelCount = 3; |
69 const int QHttpNetworkConnectionPrivate::defaultChannelCount = 3; |
70 #else |
70 #else |
71 const int QHttpNetworkConnectionPrivate::defaultChannelCount = 6; |
71 const int QHttpNetworkConnectionPrivate::defaultChannelCount = 6; |
72 #endif |
72 #endif |
73 |
73 |
74 // the maximum amount of requests that might be pipelined into a socket |
74 // The pipeline length. So there will be 4 requests in flight. |
75 // from what was suggested, 3 seems to be OK |
|
76 const int QHttpNetworkConnectionPrivate::defaultPipelineLength = 3; |
75 const int QHttpNetworkConnectionPrivate::defaultPipelineLength = 3; |
|
76 // Only re-fill the pipeline if there's defaultRePipelineLength slots free in the pipeline. |
|
77 // This means that there are 2 requests in flight and 2 slots free that will be re-filled. |
|
78 const int QHttpNetworkConnectionPrivate::defaultRePipelineLength = 2; |
77 |
79 |
78 |
80 |
79 QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt) |
81 QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt) |
80 : hostName(hostName), port(port), encrypt(encrypt), |
82 : hostName(hostName), port(port), encrypt(encrypt), |
81 channelCount(defaultChannelCount), |
83 channelCount(defaultChannelCount), |
485 if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) |
487 if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) |
486 return; |
488 return; |
487 |
489 |
488 int i = indexOf(socket); |
490 int i = indexOf(socket); |
489 |
491 |
490 bool highPriorityQueueProcessingDone = false; |
492 // return fast if there was no reply right now processed |
491 bool lowPriorityQueueProcessingDone = false; |
493 if (channels[i].reply == 0) |
492 |
494 return; |
493 while (!highPriorityQueueProcessingDone && !lowPriorityQueueProcessingDone) { |
495 |
494 // this loop runs once per request we intend to pipeline in. |
496 if (! (defaultPipelineLength - channels[i].alreadyPipelinedRequests.length() >= defaultRePipelineLength)) { |
495 |
497 return; |
496 if (channels[i].pipeliningSupported != QHttpNetworkConnectionChannel::PipeliningProbablySupported) |
498 } |
497 return; |
499 |
498 |
500 if (channels[i].pipeliningSupported != QHttpNetworkConnectionChannel::PipeliningProbablySupported) |
499 // the current request that is in must already support pipelining |
501 return; |
500 if (!channels[i].request.isPipeliningAllowed()) |
502 |
501 return; |
503 // the current request that is in must already support pipelining |
502 |
504 if (!channels[i].request.isPipeliningAllowed()) |
503 // the current request must be a idempotent (right now we only check GET) |
505 return; |
504 if (channels[i].request.operation() != QHttpNetworkRequest::Get) |
506 |
505 return; |
507 // the current request must be a idempotent (right now we only check GET) |
506 |
508 if (channels[i].request.operation() != QHttpNetworkRequest::Get) |
507 // check if socket is connected |
509 return; |
508 if (socket->state() != QAbstractSocket::ConnectedState) |
510 |
509 return; |
511 // check if socket is connected |
510 |
512 if (socket->state() != QAbstractSocket::ConnectedState) |
511 // check for resendCurrent |
513 return; |
512 if (channels[i].resendCurrent) |
514 |
513 return; |
515 // check for resendCurrent |
514 |
516 if (channels[i].resendCurrent) |
515 // we do not like authentication stuff |
517 return; |
516 // ### make sure to be OK with this in later releases |
518 |
517 if (!channels[i].authenticator.isNull() || !channels[i].authenticator.user().isEmpty()) |
519 // we do not like authentication stuff |
518 return; |
520 // ### make sure to be OK with this in later releases |
519 if (!channels[i].proxyAuthenticator.isNull() || !channels[i].proxyAuthenticator.user().isEmpty()) |
521 if (!channels[i].authenticator.isNull() || !channels[i].authenticator.user().isEmpty()) |
520 return; |
522 return; |
521 |
523 if (!channels[i].proxyAuthenticator.isNull() || !channels[i].proxyAuthenticator.user().isEmpty()) |
522 // check for pipeline length |
524 return; |
|
525 |
|
526 // must be in ReadingState or WaitingState |
|
527 if (! (channels[i].state == QHttpNetworkConnectionChannel::WaitingState |
|
528 || channels[i].state == QHttpNetworkConnectionChannel::ReadingState)) |
|
529 return; |
|
530 |
|
531 |
|
532 //qDebug() << "QHttpNetworkConnectionPrivate::fillPipeline processing highPriorityQueue, size=" << highPriorityQueue.size() << " alreadyPipelined=" << channels[i].alreadyPipelinedRequests.length(); |
|
533 int lengthBefore; |
|
534 while (!highPriorityQueue.isEmpty()) { |
|
535 lengthBefore = channels[i].alreadyPipelinedRequests.length(); |
|
536 fillPipeline(highPriorityQueue, channels[i]); |
|
537 |
523 if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) |
538 if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) |
524 return; |
539 return; |
525 |
540 |
526 // must be in ReadingState or WaitingState |
541 if (lengthBefore == channels[i].alreadyPipelinedRequests.length()) |
527 if (! (channels[i].state == QHttpNetworkConnectionChannel::WaitingState |
542 break; // did not process anything, now do the low prio queue |
528 || channels[i].state == QHttpNetworkConnectionChannel::ReadingState)) |
543 } |
|
544 |
|
545 //qDebug() << "QHttpNetworkConnectionPrivate::fillPipeline processing lowPriorityQueue, size=" << lowPriorityQueue.size() << " alreadyPipelined=" << channels[i].alreadyPipelinedRequests.length(); |
|
546 while (!lowPriorityQueue.isEmpty()) { |
|
547 lengthBefore = channels[i].alreadyPipelinedRequests.length(); |
|
548 fillPipeline(lowPriorityQueue, channels[i]); |
|
549 |
|
550 if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) |
529 return; |
551 return; |
530 |
552 |
531 highPriorityQueueProcessingDone = fillPipeline(highPriorityQueue, channels[i]); |
553 if (lengthBefore == channels[i].alreadyPipelinedRequests.length()) |
532 // not finished with highPriorityQueue? then loop again |
554 break; // did not process anything |
533 if (!highPriorityQueueProcessingDone) |
555 } |
534 continue; |
556 |
535 // highPriorityQueue was processed, now deal with the lowPriorityQueue |
557 |
536 lowPriorityQueueProcessingDone = fillPipeline(lowPriorityQueue, channels[i]); |
|
537 } |
|
538 } |
558 } |
539 |
559 |
540 // returns true when the processing of a queue has been done |
560 // returns true when the processing of a queue has been done |
541 bool QHttpNetworkConnectionPrivate::fillPipeline(QList<HttpMessagePair> &queue, QHttpNetworkConnectionChannel &channel) |
561 bool QHttpNetworkConnectionPrivate::fillPipeline(QList<HttpMessagePair> &queue, QHttpNetworkConnectionChannel &channel) |
542 { |
562 { |
745 // on the connected sockets |
764 // on the connected sockets |
746 //tryToFillPipeline(socket); |
765 //tryToFillPipeline(socket); |
747 // return fast if there is nothing to pipeline |
766 // return fast if there is nothing to pipeline |
748 if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) |
767 if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) |
749 return; |
768 return; |
750 for (int j = 0; j < channelCount; j++) |
769 for (int i = 0; i < channelCount; i++) |
751 fillPipeline(channels[j].socket); |
770 if (channels[i].socket->state() == QAbstractSocket::ConnectedState) |
|
771 fillPipeline(channels[i].socket); |
752 } |
772 } |
753 |
773 |
754 void QHttpNetworkConnectionPrivate::_q_restartAuthPendingRequests() |
774 void QHttpNetworkConnectionPrivate::_q_restartAuthPendingRequests() |
755 { |
775 { |
756 // send the request using the idle socket |
776 // send the request using the idle socket |