repo: skip data migrations if repo lock cannot be taken

Summary: This avoids deadlock with edenfs-triggered debugimporthelper.

Reviewed By: simpkins

Differential Revision: D20270678

fbshipit-source-id: 6d3e7664b375d10ad2a8caeecaef5fa895264472
This commit is contained in:
Jun Wu 2020-03-05 11:39:12 -08:00 committed by Facebook Github Bot
parent 9e87cf0897
commit 3e80ba4f99
3 changed files with 40 additions and 20 deletions

View File

@ -579,6 +579,16 @@ class localrepository(object):
# generic mapping between names and nodes # generic mapping between names and nodes
self.names = namespaces.namespaces(self) self.names = namespaces.namespaces(self)
self._eventreporting = True
try:
self._svfsmigration()
self._narrowheadsmigration()
self._zstorecommitdatamigration()
except errormod.LockHeld:
# Not fatal.
pass
def _svfsmigration(self):
# Migrate 'remotenames' and 'bookmarks' state from sharedvfs to # Migrate 'remotenames' and 'bookmarks' state from sharedvfs to
# storevfs. # storevfs.
# This cannot be safely done in the remotenames extension because # This cannot be safely done in the remotenames extension because
@ -586,15 +596,11 @@ class localrepository(object):
# use changelog before 'remotenames.reposetup'. # use changelog before 'remotenames.reposetup'.
for name in ["remotenames", "bookmarks"]: for name in ["remotenames", "bookmarks"]:
if self.sharedvfs.exists(name) and not os.path.exists(self.svfs.join(name)): if self.sharedvfs.exists(name) and not os.path.exists(self.svfs.join(name)):
with self.wlock(), self.lock(): with self.wlock(wait=False), self.lock(wait=False):
data = self.sharedvfs.read(name) data = self.sharedvfs.read(name)
# avoid svfs.write so it does not write into metalog. # avoid svfs.write so it does not write into metalog.
util.writefile(self.svfs.join(name), data) util.writefile(self.svfs.join(name), data)
self._narrowheadsmigration()
self._zstorecommitdatamigration()
self._eventreporting = True
def _narrowheadsmigration(self): def _narrowheadsmigration(self):
"""Migrate if 'narrow-heads' config has changed.""" """Migrate if 'narrow-heads' config has changed."""
narrowheadsdesired = self.ui.configbool("experimental", "narrow-heads") narrowheadsdesired = self.ui.configbool("experimental", "narrow-heads")
@ -613,13 +619,13 @@ class localrepository(object):
if narrowheadsdesired != narrowheadscurrent: if narrowheadsdesired != narrowheadscurrent:
if narrowheadsdesired: if narrowheadsdesired:
# Migrating up is easy: Just add the requirement. # Migrating up is easy: Just add the requirement.
self.ui.write_err( with self.lock(wait=False):
_( self.ui.write_err(
"migrating repo to new-style visibility and phases\n" _(
"(this does not affect most workflows; post in Source Control @ FB if you have issues)\n" "migrating repo to new-style visibility and phases\n"
"(this does not affect most workflows; post in Source Control @ FB if you have issues)\n"
)
) )
)
with self.lock():
self.storerequirements.add("narrowheads") self.storerequirements.add("narrowheads")
self._writestorerequirements() self._writestorerequirements()
else: else:
@ -627,14 +633,14 @@ class localrepository(object):
# For this invocation, still pretend that we use narrow-heads. # For this invocation, still pretend that we use narrow-heads.
# But the next invocation will use non-narrow-heads. # But the next invocation will use non-narrow-heads.
self.ui.setconfig("experimental", "narrow-heads", True) self.ui.setconfig("experimental", "narrow-heads", True)
# Writing to <shared repo path>/.hg/phaseroots with self.lock(wait=False):
self.ui.write_err( # Writing to <shared repo path>/.hg/phaseroots
_( self.ui.write_err(
"migrating repo to old-style visibility and phases\n" _(
"(this restores the behavior to a known good state; post in Source Control @ FB if you have issues)\n" "migrating repo to old-style visibility and phases\n"
"(this restores the behavior to a known good state; post in Source Control @ FB if you have issues)\n"
)
) )
)
with self.lock():
# Accessing the raw file directly without going through # Accessing the raw file directly without going through
# complicated phasescache APIs. # complicated phasescache APIs.
draftroots = self.nodes("roots(draft())") draftroots = self.nodes("roots(draft())")
@ -668,13 +674,13 @@ class localrepository(object):
if zstorecommitdatadesired: if zstorecommitdatadesired:
# Migrating up. Read all commits in revlog and store them in # Migrating up. Read all commits in revlog and store them in
# zstore. # zstore.
with self.lock(): with self.lock(wait=False):
self._syncrevlogtozstore() self._syncrevlogtozstore()
self.storerequirements.add("zstorecommitdata") self.storerequirements.add("zstorecommitdata")
self._writestorerequirements() self._writestorerequirements()
else: else:
# Migrating down is just removing the store requirement. # Migrating down is just removing the store requirement.
with self.lock(): with self.lock(wait=False):
self.storerequirements.remove("zstorecommitdata") self.storerequirements.remove("zstorecommitdata")
self._writestorerequirements() self._writestorerequirements()

View File

@ -302,6 +302,15 @@ class lock(object):
return return
assert self._lockfd is None assert self._lockfd is None
retry = 5 retry = 5
path = self.vfs.join(self.f)
if (
util.istest()
and self.f
in encoding.environ.get("EDENSCM_TEST_PRETEND_LOCKED", "").split()
):
raise error.LockHeld(errno.EAGAIN, path, self.desc, None)
while not self.held and retry: while not self.held and retry:
retry -= 1 retry -= 1
try: try:

View File

@ -23,6 +23,11 @@ Make 'B' public, and 'C' draft.
Migrate down. Migrate down.
$ setconfig experimental.narrow-heads=false $ setconfig experimental.narrow-heads=false
(Test if the repo is locked, the auto migration is skipped)
$ EDENSCM_TEST_PRETEND_LOCKED=lock hg phase $B
112478962961147124edd43549aedd1a335e44bf: public
$ hg phase $B $ hg phase $B
migrating repo to old-style visibility and phases migrating repo to old-style visibility and phases
(this restores the behavior to a known good state; post in Source Control @ FB if you have issues) (this restores the behavior to a known good state; post in Source Control @ FB if you have issues)