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