Commit Graph

18 Commits

Author SHA1 Message Date
Gregory Szorc
1f0f04ac82 clonebundles: reference correct config option
This option is no longer experimental.
2017-06-10 11:33:57 -07:00
Matt Harbison
7dc2c0c995 clonebundles: fix missing newline character
Previously, the line displayed as '( )' instead of '(\n)'.
2017-05-24 22:59:59 -04:00
Pierre-Yves David
1be9d3fb99 clonebundle: use 'repo.vfs' instead of 'repo.opener'
The later is a 5 years old form.
2017-03-02 03:23:18 +01:00
Augie Fackler
4e1c384d0a extensions: change magic "shipped with hg" string
I've caught multiple extensions in the wild lying about being
'internal', so it's time to move the goalposts on people. Goalpost
moving will continue until third party extensions stop trying to
defeat the system.
2016-08-23 11:26:08 -04:00
Gregory Szorc
44166bddc4 clonebundles: use absolute_import 2016-02-09 17:51:44 -08:00
Gregory Szorc
bdc9fb8c76 clonebundles: improve BUNDLESPEC documentation
Before the existence of `hg debugbundle --spec`, the process for
defining the BUNDLESPEC value in manifests was not very clear and not
trivial to automate, especially in the case of stream clone bundles.

This patch adds documentation to note the existence of
`hg debugbundle --spec`. We drop the reference to stream clone
requirements handling because it is now redundant with
`hg debugbundle --spec`. While we are here, we further reinforce the
importance of defining BUNDLESPEC.
2016-01-14 22:50:55 -08:00
Gregory Szorc
5732d02b64 exchange: make clone bundles non-experimental and enabled by default
The clone bundles feature was introduced in Mercurial 3.6 behind an
experimental and disabled by default flag. The feature has been enabled
on hg.mozilla.org for a few months and has served many terabytes of
clones. Users have been encouraged to use the feature and reception
has been very positive (mainly due to faster clones as a result of
connecting to a CDN). I have heard no feedback about changing the
feature other than inquiries about when it will be enabled by default.
So, I think the feature is ready to be enabled by default.

This patch renames experimental.clonebundles to ui.clonebundles,
documents the option, and enables it by default. References to the
experimental state of clone bundles have been removed. The remaining
config option docs in clonebundles.py have been removed because they
are redudant with `hg help config`.

There are some oddities with behavior of clone bundles. Because clones
with clone bundles are effectively 2 `hg pull` operations, there may be
2 transactions. This could result in hooks running twice. If the
subsequent pull is aborted, it could result in partial rollback and an
incomplete clone. This behavior is a bit wonky and should probably
be documented. If this patch is accepted, I'll send a follow-up to
document it. I don't think this behavior should prevent the feature
being enabled by default. Reworking the clone mechanism to support
interrupted or multi-part clones feels like a major new feature and
something that when implemented can change the hook and rollback
semantics of clone bundles. Besides, partial clone is better than
full rollback and hooks running on initial clone are likely rare, so I
think the impact is minimal.
2016-01-08 10:58:04 -08:00
Gregory Szorc
0436f8dd18 exchange: make clonebundleprefers non-experimental
In preparation for making the feature enabled by default.
2016-01-08 10:57:01 -08:00
Gregory Szorc
2c9adcd9c5 clonebundles: remove advertisement of feature
I screwed up.

When clone bundles is enabled on the server and a compatible client
without the feature enabled clones, the server sends down an
advertisement saying to enable the feature. The server creates the
message which is printed verbatim on the client as an "output" part.
There are 2 problems:

1) The message doesn't respect the client's localization
2) The message contains a reference to the "experimental.clonebundles"
   option.

Since clone bundles is about to be marked as non-experimental and the
goal of the advertisement was to encourage clients to test the
experimental feature, let's just remove the broken advertisement since
it no longer serves a purpose.
2016-01-08 10:53:07 -08:00
Mathias De Maré
0e11ed0ee2 clonebundles: fix bundlespec typo 2015-12-16 12:33:54 +01:00
Mathias De Maré
14d32d90ac clonebundles: fix typo 2015-12-15 07:17:15 +01:00
Javi Merino
65fb643f36 clonebundles: fix typo s/comand/command/ 2015-11-05 10:31:20 +00:00
Gregory Szorc
61b9ffeec8 wireproto: move clonebundles command from extension (issue4931)
The SSH peer class accesses wireproto.commands[cmd] as part of encoding
command arguments. Previously, the wire protocol command was defined in
the clonebundles extension. If the client didn't have this extension
enabled (which it likely doesn't since it is meant as a server-side
extension), then clients attempting to clone via ssh:// would get a
crash due to a KeyError accessing wireproto.commands['clonebundles']
when cloning from a server that is advertising clone bundles.

Moving the definition of the wire protocol command to wireproto.py makes
this problem go away.

A side effect of this code move is servers will always respond to
"clonebundles" wire protocol command requests. This should be fine: the
server will return an empty response unless a clone bundles manifest
file is present and clients shouldn't call the command unless the server
is advertising the capability, which only happens if the clonebundles
extension is enabled and the manifest file exists.
2015-11-03 12:31:33 -08:00
Gregory Szorc
508a4655f7 clonebundles: rewrite documentation
There are a lot of considerations server operators need to know before
deploying clone bundles. They should be documented. So I rewrote the
extension docs to contain this information.
2015-10-17 11:23:54 -07:00
Gregory Szorc
15ac94d01f clonebundles: advertise clone bundles feature to clients
Server operators that have enabled clone bundles probably want clients
to use it. This patch introduces a feature that will insert a bundle2
"output" part that advertises the existence of the clone bundles
feature to clients that aren't using it.

The server uses the "cbattempted" argument to "getbundle" to determine
whether a client supports clone bundles and to avoid sending the message
to clients that failed the clone bundle for whatever reason.
2015-10-14 11:05:53 -07:00
Gregory Szorc
7f6305218b clonebundles: filter on SNI requirement
Server Name Indication (SNI) is commonly used in CDNs and other hosted
environments. Unfortunately, Python <2.7.9 does not support SNI and when
these older Python versions attempt to negotiate TLS to an SNI server,
they raise an opaque error like
"_ssl.c:507: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert
handshake failure."

We introduce a manifest attribute to denote the URL requires SNI and
have clients without SNI support filter these entries.
2015-10-13 10:59:41 -07:00
Gregory Szorc
11b70bd7bb clonebundles: filter on bundle specification
Not all clients are capable of reading every bundle. Currently, content
negotiation to ensure a server sends a client a compatible bundle
format is performed at request time. The response bundle is dynamically
generated at request time, so this works fine.

Clone bundles are statically generated *before* the request. This means
that a modern server could produce bundles that a legacy client isn't
capable of reading. Without some kind of "type hint" in the clone
bundles manifest, a client may attempt to download an incompatible
bundle. Furthermore, a client may not realize a bundle is incompatible
until it has processed part of the bundle (imagine consuming a 1 GB
changegroup bundle2 part only to discover the bundle2 part afterwards is
incompatibl). This would waste time and resources. And it isn't very
user friendly.

Clone bundle manifests thus need to advertise the *exact* format of the
hosted bundles so clients may filter out entries that they don't know
how to read. This patch introduces that mechanism.

We introduce the BUNDLESPEC attribute to declare the "bundle
specification" of the entry. Bundle specifications are parsed using
exchange.parsebundlespecification, which uses the same strings as the
"--type" argument to `hg bundle`. The supported bundle specifications
are well defined and backwards compatible.

When a client encounters a BUNDLESPEC that is invalid or unsupported, it
silently ignores the entry.
2015-10-13 11:45:30 -07:00
Gregory Szorc
5d1b4c49ee clonebundles: support for seeding clones from pre-generated bundles
Cloning can be an expensive operation for servers because the server
generates a bundle from existing repository data at request time. For
a large repository like mozilla-central, this consumes 4+ minutes
of CPU time on the server. It also results in significant network
utilization. Multiplied by hundreds or even thousands of clients and
the ensuing load can result in difficulties scaling the Mercurial server.

Despite generation of bundles being deterministic until the next
changeset is added, the generation of bundles to service a clone request
is not cached. Each clone thus performs redundant work. This is
wasteful.

This patch introduces the "clonebundles" extension and related
client-side functionality to help alleviate this deficiency. The
client-side feature is behind an experimental flag and is not enabled by
default.

It works as follows:

1) Server operator generates a bundle and makes it available on a
   server (likely HTTP).
2) Server operator defines the URL of a bundle file in a
   .hg/clonebundles.manifest file.
3) Client `hg clone`ing sees the server is advertising bundle URLs.
4) Client fetches and applies the advertised bundle.
5) Client performs equivalent of `hg pull` to fetch changes made since
   the bundle was created.

Essentially, the server performs the expensive work of generating a
bundle once and all subsequent clones fetch a static file from
somewhere. Scaling static file serving is a much more manageable
problem than scaling a Python application like Mercurial. Assuming your
repository grows less than 1% per day, the end result is 99+% of CPU
and network load from clones is eliminated, allowing Mercurial servers
to scale more easily. Serving static files also means data can be
transferred to clients as fast as they can consume it, rather than as
fast as servers can generate it. This makes clones faster.

Mozilla has implemented similar functionality of this patch on
hg.mozilla.org using a custom extension. We are hosting bundle files in
Amazon S3 and CloudFront (a CDN) and have successfully offloaded
>1 TB/day in data transfer from hg.mozilla.org, freeing up significant
bandwidth and CPU resources. The positive impact has been stellar and
I believe it has proved its value to be included in Mercurial core. I
feel it is important for the client-side support to be enabled in core
by default because it means that clients will get faster, more reliable
clones and will enable server operators to reduce load without
requiring any client-side configuration changes (assuming clients are
up to date, of course).

The scope of this feature is narrowly and specifically tailored to
cloning, despite "serve pulls from pre-generated bundles" being a valid
and useful feature. I would eventually like for Mercurial servers to
support transferring *all* repository data via statically hosted files.
You could imagine a server that siphons all pushed data to bundle files
and instructs clients to apply a stream of bundles to reconstruct all
repository data. This feature, while useful and powerful, is
significantly more work to implement because it requires the server
component have awareness of discovery and a mapping of which changesets
are in which files. Full, clone bundles, by contrast, are much simpler.

The wire protocol command is named "clonebundles" instead of something
more generic like "staticbundles" to leave the door open for a new, more
powerful and more generic server-side component with minimal backwards
compatibility implications. The name "bundleclone" is used by Mozilla's
extension and would cause problems since there are subtle differences
in Mozilla's extension.

Mozilla's experience with this idea has taught us that some form of
"content negotiation" is required. Not all clients will support all
bundle formats or even URLs (advanced TLS requirements, etc). To ensure
the highest uptake possible, a server needs to advertise multiple
versions of bundles and clients need to be able to choose the most
appropriate from that list one. The "attributes" in each
server-advertised entry facilitate this filtering and sorting. Their
use will become apparent in subsequent patches.

Initial inspiration and credit for the idea of cloning from static files
belongs to Augie Fackler and his "lookaside clone" extension proof of
concept.
2015-10-09 11:22:01 -07:00