tests/test-revlog-ancestry.py
author Matt Harbison <matt_harbison@yahoo.com>
Tue, 21 Jan 2020 11:32:33 -0500
changeset 44320 43eea17ae7b3
parent 43076 2372284d9457
child 44431 0e5e192adb6f
permissions -rw-r--r--
lfs: fix the stall and corruption issue when concurrently uploading blobs We've avoided the issue up to this point by gating worker usage with an experimental config. See 10e62d5efa73, and the thread linked there for some of the initial diagnosis, but essentially some data was being read from the blob before an error occurred and `keepalive` retried, but didn't rewind the file pointer. So the leading data was lost from the blob on the server, and the connection stalled, trying to send more data than available. In trying to recreate this, I was unable to do so uploading from Windows to CentOS 7. But it reproduced every time going from CentOS 7 to another CentOS 7 over https. I found recent fixes in the FaceBook repo to address this[1][2]. The commit message for the first is: The KeepAlive HTTP implementation is bugged in it's retry logic, it supports reading from a file pointer, but doesn't support rewinding of the seek cursor when it performs a retry. So it can happen that an upload fails for whatever reason and will then 'hang' on the retry event. The sequence of events that get triggered are: - Upload file A, goes OK. Keep-Alive caches connection. - Upload file B, fails due to (for example) failing Keep-Alive, but LFS file pointer has been consumed for the upload and fd has been closed. - Retry for file B starts, sets the Content-Length properly to the expected file size, but since file pointer has been consumed no data will be uploaded, causing the server to wait for the uploaded data until either client or server reaches a timeout, making it seem as our mercurial process hangs. This is just a stop-gap measure to prevent this behavior from blocking Mercurial (LFS has retry logic). A proper solutions need to be build on top of this stop-gap measure: for upload from file pointers, we should support fseek() on the interface. Since we expect to consume the whole file always anyways, this should be safe. This way we can seek back to the beginning on a retry. I ported those two patches, and it works. But I see that `url._sendfile()` does a rewind on `httpsendfile` objects[3], so maybe it's better to keep this all in one place and avoid a second seek. We may still want the first FaceBook patch as extra protection for this problem in general. The other two uses of `httpsendfile` are in the wire protocol to upload bundles, and to upload largefiles. Neither of these appear to use a worker, and I'm not sure why workers seem to trigger this, or if this could have happened without a worker. Since `httpsendfile` already has a `close()` method, that is dropped. That class also explicitly says there's no `__len__` attribute, so that is removed too. The override for `read()` is necessary to avoid the progressbar usage per file. [1] https://github.com/facebookexperimental/eden/commit/c350d6536d90c044c837abdd3675185644481469 [2] https://github.com/facebookexperimental/eden/commit/77f0d3fd0415e81b63e317e457af9c55c46103ee [3] https://www.mercurial-scm.org/repo/hg/file/5.2.2/mercurial/url.py#l176 Differential Revision: https://phab.mercurial-scm.org/D7962
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
     1
from __future__ import absolute_import, print_function
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
     2
import os
28763
abe605bbf0de py3: use absolute_import in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 27344
diff changeset
     3
from mercurial import (
abe605bbf0de py3: use absolute_import in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 27344
diff changeset
     4
    hg,
abe605bbf0de py3: use absolute_import in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 27344
diff changeset
     5
    merge,
28842
d466facc5a6e tests: alias ui as uimod in test-revlog-ancestry/test-ui-verbosity
Yuya Nishihara <yuya@tcha.org>
parents: 28764
diff changeset
     6
    ui as uimod,
28763
abe605bbf0de py3: use absolute_import in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 27344
diff changeset
     7
)
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
     8
30564
d83ca854fa21 ui: factor out ui.load() to create a ui without loading configs (API)
Yuya Nishihara <yuya@tcha.org>
parents: 28842
diff changeset
     9
u = uimod.ui.load()
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    10
36512
14d2371216ba py3: add b'' prefixes in tests/test-revlog-ancestry.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30564
diff changeset
    11
repo = hg.repository(u, b'test1', create=1)
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    12
os.chdir('test1')
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    13
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40366
diff changeset
    14
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    15
def commit(text, time):
36512
14d2371216ba py3: add b'' prefixes in tests/test-revlog-ancestry.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30564
diff changeset
    16
    repo.commit(text=text, date=b"%d 0" % time)
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    17
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40366
diff changeset
    18
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    19
def addcommit(name, time):
36513
5a029f049854 py3: make sure we open the file in bytes mode
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36512
diff changeset
    20
    f = open(name, 'wb')
36512
14d2371216ba py3: add b'' prefixes in tests/test-revlog-ancestry.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30564
diff changeset
    21
    f.write(b'%s\n' % name)
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    22
    f.close()
11303
a1aad8333864 move working dir/dirstate methods from localrepo to workingctx
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9031
diff changeset
    23
    repo[None].add([name])
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    24
    commit(name, time)
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    25
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40366
diff changeset
    26
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    27
def update(rev):
40366
b14fdf1fb615 update: clarify update() call sites by specifying argument names
Martin von Zweigbergk <martinvonz@google.com>
parents: 36513
diff changeset
    28
    merge.update(repo, rev, branchmerge=False, force=True)
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    29
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40366
diff changeset
    30
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    31
def merge_(rev):
40366
b14fdf1fb615 update: clarify update() call sites by specifying argument names
Martin von Zweigbergk <martinvonz@google.com>
parents: 36513
diff changeset
    32
    merge.update(repo, rev, branchmerge=True, force=False)
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    33
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40366
diff changeset
    34
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    35
if __name__ == '__main__':
36512
14d2371216ba py3: add b'' prefixes in tests/test-revlog-ancestry.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30564
diff changeset
    36
    addcommit(b"A", 0)
14d2371216ba py3: add b'' prefixes in tests/test-revlog-ancestry.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30564
diff changeset
    37
    addcommit(b"B", 1)
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    38
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    39
    update(0)
36512
14d2371216ba py3: add b'' prefixes in tests/test-revlog-ancestry.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30564
diff changeset
    40
    addcommit(b"C", 2)
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    41
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    42
    merge_(1)
36512
14d2371216ba py3: add b'' prefixes in tests/test-revlog-ancestry.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30564
diff changeset
    43
    commit(b"D", 3)
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    44
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    45
    update(2)
36512
14d2371216ba py3: add b'' prefixes in tests/test-revlog-ancestry.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30564
diff changeset
    46
    addcommit(b"E", 4)
14d2371216ba py3: add b'' prefixes in tests/test-revlog-ancestry.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30564
diff changeset
    47
    addcommit(b"F", 5)
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    48
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    49
    update(3)
36512
14d2371216ba py3: add b'' prefixes in tests/test-revlog-ancestry.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30564
diff changeset
    50
    addcommit(b"G", 6)
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    51
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    52
    merge_(5)
36512
14d2371216ba py3: add b'' prefixes in tests/test-revlog-ancestry.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30564
diff changeset
    53
    commit(b"H", 7)
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    54
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    55
    update(5)
36512
14d2371216ba py3: add b'' prefixes in tests/test-revlog-ancestry.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30564
diff changeset
    56
    addcommit(b"I", 8)
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    57
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    58
    # Ancestors
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    59
    print('Ancestors of 5')
16866
91f3ac205816 revlog: ancestors(*revs) becomes ancestors(revs) (API)
Bryan O'Sullivan <bryano@fb.com>
parents: 11303
diff changeset
    60
    for r in repo.changelog.ancestors([5]):
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    61
        print(r, end=' ')
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    62
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    63
    print('\nAncestors of 6 and 5')
16866
91f3ac205816 revlog: ancestors(*revs) becomes ancestors(revs) (API)
Bryan O'Sullivan <bryano@fb.com>
parents: 11303
diff changeset
    64
    for r in repo.changelog.ancestors([6, 5]):
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    65
        print(r, end=' ')
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    66
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    67
    print('\nAncestors of 5 and 4')
16866
91f3ac205816 revlog: ancestors(*revs) becomes ancestors(revs) (API)
Bryan O'Sullivan <bryano@fb.com>
parents: 11303
diff changeset
    68
    for r in repo.changelog.ancestors([5, 4]):
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    69
        print(r, end=' ')
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    70
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    71
    print('\nAncestors of 7, stop at 6')
16868
eb88ed4269c5 revlog: add optional stoprev arg to revlog.ancestors()
Joshua Redstone <joshua.redstone@fb.com>
parents: 16867
diff changeset
    72
    for r in repo.changelog.ancestors([7], 6):
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    73
        print(r, end=' ')
16868
eb88ed4269c5 revlog: add optional stoprev arg to revlog.ancestors()
Joshua Redstone <joshua.redstone@fb.com>
parents: 16867
diff changeset
    74
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    75
    print('\nAncestors of 7, including revs')
18081
f88c60e740a1 revlog.ancestors: add support for including revs
Siddharth Agarwal <sid0@fb.com>
parents: 16868
diff changeset
    76
    for r in repo.changelog.ancestors([7], inclusive=True):
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    77
        print(r, end=' ')
18081
f88c60e740a1 revlog.ancestors: add support for including revs
Siddharth Agarwal <sid0@fb.com>
parents: 16868
diff changeset
    78
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    79
    print('\nAncestors of 7, 5 and 3, including revs')
18081
f88c60e740a1 revlog.ancestors: add support for including revs
Siddharth Agarwal <sid0@fb.com>
parents: 16868
diff changeset
    80
    for r in repo.changelog.ancestors([7, 5, 3], inclusive=True):
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    81
        print(r, end=' ')
18081
f88c60e740a1 revlog.ancestors: add support for including revs
Siddharth Agarwal <sid0@fb.com>
parents: 16868
diff changeset
    82
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    83
    # Descendants
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    84
    print('\n\nDescendants of 5')
16867
1093ad1e8903 revlog: descendants(*revs) becomes descendants(revs) (API)
Bryan O'Sullivan <bryano@fb.com>
parents: 16866
diff changeset
    85
    for r in repo.changelog.descendants([5]):
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    86
        print(r, end=' ')
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    87
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    88
    print('\nDescendants of 5 and 3')
16867
1093ad1e8903 revlog: descendants(*revs) becomes descendants(revs) (API)
Bryan O'Sullivan <bryano@fb.com>
parents: 16866
diff changeset
    89
    for r in repo.changelog.descendants([5, 3]):
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    90
        print(r, end=' ')
6872
c7cc40fd74f6 Add ancestors and descendants to revlog
Stefano Tortarolo <stefano.tortarolo@gmail.com>
parents:
diff changeset
    91
28764
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    92
    print('\nDescendants of 5 and 4')
e677b8daeb3f py3: use print_function in test-revlog-ancestry.py
Robert Stanca <robert.stanca7@gmail.com>
parents: 28763
diff changeset
    93
    print(*repo.changelog.descendants([5, 4]), sep=' ')