remotenames: separate lock for the accessed bookmarks file

Summary:
File that tracks accessed bookmarks doesn't interact with anything else and doesn't really need repo.wlock. However if does use wlock, hg commands like `hg log -r`, which normally are read-only, start waiting for the lock and thus are blocked by other writing commands, that might be running in different checkouts of the same repo.

Let's use a different lock for this feature.

Reviewed By: simpkins

Differential Revision: D15165788

fbshipit-source-id: f04c7196d51db67069c6420545be24d2b7c0af27
This commit is contained in:
Aida Getoeva 2019-05-03 06:45:53 -07:00 committed by Facebook Github Bot
parent 75ca3f73f7
commit 10e0a1143a

View File

@ -96,6 +96,8 @@ journalremotebookmarktype = "remotebookmark"
# happened
_selectivepullenabledfile = "selectivepullenabled"
_selectivepullaccessedbookmarks = "selectivepullaccessedbookmarks"
# separate lock to update accessed bookmarks
_selectivepullaccessedbookmarkslock = "selectivepullaccessedbookmarks.lock"
def exbookcalcupdate(orig, ui, repo, checkout):
@ -195,33 +197,31 @@ def updateaccessedbookmarks(repo, remotepath, bookmarks):
vfs = repo.sharedvfs
if vfs.exists(_selectivepullaccessedbookmarks):
knownbooks = set(_readremotenamesfrom(vfs, _selectivepullaccessedbookmarks))
else:
knownbooks = set()
totalaccessednames = 0
with repo.wlock(), vfs(_selectivepullaccessedbookmarks, "w", atomictemp=True) as f:
newbookmarks = {}
for node, nametype, oldremote, rname in knownbooks:
if nametype != "bookmarks":
continue
with lockmod.lock(vfs, _selectivepullaccessedbookmarkslock):
knownbooks = set(_readremotenamesfrom(vfs, _selectivepullaccessedbookmarks))
if oldremote != remotepath:
with vfs(_selectivepullaccessedbookmarks, "w", atomictemp=True) as f:
newbookmarks = {}
for node, nametype, oldremote, rname in knownbooks:
if nametype != "bookmarks":
continue
if oldremote != remotepath:
totalaccessednames += 1
_writesingleremotename(f, oldremote, nametype, rname, node)
else:
newbookmarks[rname] = node
nodemap = repo.unfiltered().changelog.nodemap
for rname, node in bookmarks.iteritems():
# if the node is known locally, update the old value or add new
if bin(node) in nodemap:
newbookmarks[rname] = node
for rname, node in newbookmarks.iteritems():
totalaccessednames += 1
_writesingleremotename(f, oldremote, nametype, rname, node)
else:
newbookmarks[rname] = node
nodemap = repo.unfiltered().changelog.nodemap
for rname, node in bookmarks.iteritems():
# if the node is known locally, update the old value or add new
if bin(node) in nodemap:
newbookmarks[rname] = node
for rname, node in newbookmarks.iteritems():
totalaccessednames += 1
_writesingleremotename(f, remotepath, "bookmarks", rname, node)
_writesingleremotename(f, remotepath, "bookmarks", rname, node)
# log the number of accessed bookmarks currently tracked
repo.ui.log("accessedremotenames", accessedremotenames_totalnum=totalaccessednames)
@ -940,6 +940,8 @@ def extsetup(ui):
bookcmd = extensions.wrapcommand(commands.table, "bookmarks", exbookmarks)
pushcmd = extensions.wrapcommand(commands.table, "push", expushcmd)
localrepo.localrepository._wlockfreeprefix.add("selectivepullaccessedbookmarks")
if _tracking(ui):
bookcmd[1].append(
("t", "track", "", "track this bookmark or remote name", "BOOKMARK")
@ -1639,33 +1641,35 @@ def shareawarecachevfs(repo):
def _readremotenamesfrom(vfs, filename):
if not vfs.exists(filename):
try:
f = vfs(filename)
except EnvironmentError as er:
if er.errno != errno.ENOENT:
raise
return
f = vfs(filename)
for line in f:
nametype = None
line = line.strip()
if not line:
continue
nametype = None
remote, rname = None, None
with f:
for line in f:
nametype = None
line = line.strip()
if not line:
continue
nametype = None
remote, rname = None, None
node, name = line.split(" ", 1)
node, name = line.split(" ", 1)
# check for nametype being written into the file format
if " " in name:
nametype, name = name.split(" ", 1)
# check for nametype being written into the file format
if " " in name:
nametype, name = name.split(" ", 1)
remote, rname = splitremotename(name)
remote, rname = splitremotename(name)
# skip old data that didn't write the name (only wrote the alias)
if not rname:
continue
# skip old data that didn't write the name (only wrote the alias)
if not rname:
continue
yield node, nametype, remote, rname
f.close()
yield node, nametype, remote, rname
def readbookmarknames(repo, remote):