Bug 3567 - hg not sending authentication on clone operations on the first try
Summary: hg not sending authentication on clone operations on the first try
Status: RESOLVED FIXED
Alias: None
Product: Mercurial
Classification: Unclassified
Component: Mercurial (show other bugs)
Version: earlier
Hardware: PC Windows
: normal bug
Assignee: Bugzilla
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-08-01 18:32 UTC by Jason Jelinek
Modified: 2017-11-01 18:04 UTC (History)
6 users (show)

See Also:
Python Version: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jason Jelinek 2012-08-01 18:32 UTC
I have noticed that during a clone of a repo there are 5 requests being sent, each taking 1 second, on the first try for all 5 requests the authentication is not being sent.  After those requests fail (returns a 401), it retries all 5 requests with the authentication and works.  It would seem that after the very 1st request fails it should send the authentication and the rest of the 4 requests should send authentication on the first try.

This is a huge slowdown when cloning a repo with subrepos in it.  We have 360+ subrepos and it retries the 5 requests for every subrepo.  This translates to around 30 minutes of failed retries.  A clone currently takes 54+ minutes but if authentication is turned off it only takes 24 minutes.
Comment 1 kiilerix 2012-08-01 19:42 UTC
You don't mention any context. I assume you are using plain http and basic authentication and hgweb.wsgi on apache on a LAN?

Some reasons this doesn't work as smooth as one could imagine:
* the http standards
* the python http library API and implementation - especially in older python versions
* the way Mercurial uses the python http library
* that you are using subrepos which are completely independent repos that are stitched together.

The http authentication issue usually only drags attention when making big pushes (twice).

You could try the experimental http library by setting [ui] usehttp2=true ... but I doubt it will make much difference for your case.

1 second roundtrip time is more than I would expect on a LAN. You could try to look into where that time is spent and optimize that.

If cloning is your primary issue you could look intro creating a zip with the whole tree of repos that could be downloaded and extracted instead of cloning the usual way.

But perhaps most important: 360+ subrepos do really not sound like a good idea. You will suffer a lot from scalability issues in areas where nobody else cares because everybody else only cares about 'scaling' to one or a few.
Comment 2 Paul Nathan 2012-08-01 20:00 UTC
Actually, we use subrepos counts upto and in excess of 100 per project. 

While we've been working on internal tooling to help improve our workflows (& move away from subrepos), this is something that actually matters a LOT.
Comment 3 Augie Fackler 2012-08-01 21:50 UTC
http2 doesn't (yet) help with the no-auth-on-first-attempt problem. I'm still formulating ideas for that.
Comment 4 kiilerix 2012-08-03 08:15 UTC
2 c:

In my http implementation I have a "global" map that keeps track of which servers requested which kinds of authentication. Once that has been established in the very first request it is used to jump start subsequent requests for other resources.

I also have an option for initiating authentication in the very first request, before it has been requested by the server. That is probably not relevant for Mercurial where the very first request is small and the overhead of an extra roundtrip of that doesn't matter much.

Handling the rfc 2617 "protection space" (realm and path) "correctly" is hard and probably inefficient. It is often not necessary to handle that correctly, but I'm in doubt whether it always makes sense to reuse authentication across subrepos.
Comment 5 Jason Jelinek 2012-08-07 15:27 UTC
The context is the following:
- https
- hgweb using cgi on IIS
- on a WAN

I'm not sure creating a zip would work with sub-repos. A zip of a repo that doesn't have anything in the working directory would force a clone of all the sub-repos when the repo was updated.

The repo we would be cloning would reside on our server to clone/push/pull from, we would be using Jenkins to clone on our server and update the clone to do the build.
Comment 6 kiilerix 2012-08-08 06:34 UTC
(In reply to comment #5)

It should be a zip with nothing in the working directory except .hg folders of subrepos. 'hg update' will only do a pull if the referenced revision doesn't exist in the existing local sub repo.
Comment 7 HG Bot 2013-12-16 15:00 UTC
Fixed by http://selenic.com/repo/hg/rev/181108726ea5
St?phane Klein <contact@stephane-klein.info>
http: reuse authentication info after the first failed request (issue3567)

Context: mercurial access to repository server with http access, and this
server is protected by basic auth.

Before patch:

* mercurial try an anonymous access to server, server return 401 response and
  mercurial resend request with login / password information

After patch:

* mercurial try an anonymous access to server, server return 401
  response. For all subsequent requests, mercurial keep in memory this
  information (this server need basic auth information).

This patch reduce the number of http access against mercurial server.

Example, before patch :

10.10.168.170 - - [25/Oct/2013:15:44:51 +0200] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:44:52 +0200] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 200 147 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:00 +0200] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:01 +0200] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 200 147 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:03 +0200] "GET /hg/testagt?cmd=batch
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:04 +0200] "GET /hg/testagt?cmd=batch
HTTP/1.1" 200 42 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:06 +0200] "GET /hg/testagt?cmd=getbundle
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:07 +0200] "GET /hg/testagt?cmd=getbundle
HTTP/1.1" 200 61184 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:09 +0200] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:10 +0200] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 200 15 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:12 +0200] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:12 +0200] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 200 - "-" "mercurial/proto-1.0"

Example after patch :

10.10.168.170 - - [28/Oct/2013:11:49:14 +0100] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:15 +0100] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 200 147 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:17 +0100] "GET /hg/testagt?cmd=batch
HTTP/1.1" 200 42 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:19 +0100] "GET /hg/testagt?cmd=getbundle
HTTP/1.1" 200 61184 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:22 +0100] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 200 15 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:24 +0100] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 200 - "-" "mercurial/proto-1.0"

In this last example, you can see only one 401 response.

(please test the fix)
Comment 8 Augie Fackler 2013-12-16 15:08 UTC
I had to back that changeset out -> back to in progress because bz won't let me just make this open.
Comment 9 Augie Fackler 2013-12-16 15:08 UTC
(Back to confirmed.)
Comment 10 HG Bot 2014-04-10 12:45 UTC
Fixed by http://selenic.com/repo/hg/rev/a939eeb94833
St?phane Klein <contact@stephane-klein.info>
http: reuse authentication info after the first failed request (issue3567)

[This was applied in 181108726ea5 but backed out again in af02783dea65 because
of Python 2.4 issues. This edition and test-http.t works with Python 2.4.]

Context: mercurial access to repository server with http access, and this
server is protected by basic auth.

Before patch:

* mercurial try an anonymous access to server, server return 401 response and
  mercurial resend request with login / password information

After patch:

* mercurial try an anonymous access to server, server return
  401 response. For all next requests, mercurial keep in memory this
  information (this server need basic auth information).

This patch reduce the number of http access against mercurial server.

Example, before patch:

10.10.168.170 - - [25/Oct/2013:15:44:51 +0200] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:44:52 +0200] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 200 147 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:00 +0200] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:01 +0200] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 200 147 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:03 +0200] "GET /hg/testagt?cmd=batch
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:04 +0200] "GET /hg/testagt?cmd=batch
HTTP/1.1" 200 42 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:06 +0200] "GET /hg/testagt?cmd=getbundle
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:07 +0200] "GET /hg/testagt?cmd=getbundle
HTTP/1.1" 200 61184 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:09 +0200] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:10 +0200] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 200 15 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:12 +0200] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:12 +0200] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 200 - "-" "mercurial/proto-1.0"

Example after patch:

10.10.168.170 - - [28/Oct/2013:11:49:14 +0100] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:15 +0100] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 200 147 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:17 +0100] "GET /hg/testagt?cmd=batch
HTTP/1.1" 200 42 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:19 +0100] "GET /hg/testagt?cmd=getbundle
HTTP/1.1" 200 61184 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:22 +0100] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 200 15 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:24 +0100] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 200 - "-" "mercurial/proto-1.0"

In this last example, you can see only one 401 response.

(please test the fix)