sapling/tests/test-hgsql-sync.t
Jun Wu 3ee1c205cd hgsql: sync repos before acquiring the SQL write lock
Summary:
When entering the critical section (creating a transaction), hgsql might wait
for SQL lock for a long time (minutes). And it currently does nothing during
that wait time. If the lock was acquired after a long time, the work of
catching up with what the database already has might be too much. That is a
waste within the precious hgsql lock held critical section.

Instead of waiting for the lock for N seconds and doing nothing, wait for k
(k < N) seconds and also try to sync with SQL periodically. This makes the
repo closer to what the database has and can reduce work needed to pull from
the database in the critical section.

This adds CPU pressure to the MySQL tier. I added a config option to control
it.  Worse case, we can change `hgsql.syncinterval` to make the sync less
frequent.

As we're here, try document the configs.

Reviewed By: phillco

Differential Revision: D10002578

fbshipit-source-id: bd72d8225c919aa2bc62743de1e1d3f27cba606a
2018-09-25 16:06:20 -07:00

180 lines
4.9 KiB
Raku

#testcases case-innodb case-rocksdb
#if case-rocksdb
$ DBENGINE=rocksdb
#else
$ DBENGINE=innodb
#endif
$ . "$TESTDIR/hgsql/library.sh"
$ setconfig hgsql.verbose=1
# Populate the db with an initial commit
$ initclient client
$ cd client
$ echo x > x
$ hg commit -qAm x
$ cd ..
$ initserver master masterrepo
$ cd master
$ hg log
[hgsql] getting 0 commits from database
$ hg pull -q ../client
[hgsql] getting 0 commits from database
[hgsql] got lock after * seconds (glob)
[hgsql] getting 0 commits from database
[hgsql] held lock for * seconds (glob)
$ cd ..
# Verify new masters see the same commit
$ initserver master2 masterrepo
$ cd master2
$ hg log
[hgsql] getting 1 commits from database
changeset: 0:b292c1e3311f
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: x
# Push new commit to one master, verify it shows up in the other
$ cd ../client
$ echo y > y
# (also test for a file containing a single null byte)
$ printf '\0' > nullbyte
$ f --hexdump nullbyte
nullbyte:
0000: 00 |.|
$ hg commit -qAm y
$ hg push -q ssh://user@dummy/master
$ cd ../master2
$ hg log -l 1
[hgsql] getting 1 commits from database
changeset: 1:b62091368546
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: y
$ hg cat -r 1 nullbyte | f --hexdump -
0000: 00 |.|
# Push a bookmark to one master, verify in the other
$ cd ../client
$ hg book mybook
$ hg push ssh://user@dummy/master -B mybook
pushing to ssh://user@dummy/master
searching for changes
no changes found
remote: [hgsql] got lock after * seconds (glob)
remote: [hgsql] held lock for * seconds (glob)
exporting bookmark mybook
[1]
$ cd ../master2
$ hg book
[hgsql] getting 0 commits from database
mybook 1:b62091368546
# Pull commit and bookmark to one master, verify in the other
$ cd ../client
$ hg up mybook
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo z > z
$ hg commit -qAm z
$ cd ../master
$ hg pull -q ssh://user@dummy/client
[hgsql] got lock after * seconds (glob)
[hgsql] held lock for * seconds (glob)
$ cd ../master2
$ hg log -l 1
[hgsql] getting 1 commits from database
changeset: 2:f3a7cb746fa9
bookmark: mybook
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: z
# Delete a bookmark in one, verify in the other
$ hg book book1
[hgsql] got lock after * seconds (glob)
[hgsql] held lock for * seconds (glob)
$ cd ../master
$ hg book
[hgsql] getting 0 commits from database
book1 -1:000000000000
mybook 2:f3a7cb746fa9
$ hg book -d book1
[hgsql] got lock after * seconds (glob)
[hgsql] held lock for * seconds (glob)
$ cd ../master2
$ hg book
[hgsql] getting 0 commits from database
mybook 2:f3a7cb746fa9
# Verify that --forcesync works
$ cd ../
$ cp $HGRCPATH backup.hgrc
$ cd master
$ echo '[hooks]' >> $HGRCPATH
$ echo 'presyncdb=$TESTTMP/hook.sh' >> $HGRCPATH
$ echo 'sleep 2' > $TESTTMP/hook.sh
$ chmod a+x $TESTTMP/hook.sh
$ cd ../client
$ echo a > a
$ hg commit -qAm a
$ hg push -q ssh://user@dummy/master2
$ cd ../master
$ hg log -l 1 --template '{rev} {desc}\n' &
$ sleep 1
[hgsql] getting 1 commits from database
$ hg log -l 1 --template '{rev} {desc}\n' --forcesync
waiting for lock on working directory of $TESTTMP/master held by * (glob)
(hint: run 'hg debugprocesstree *' to see related processes) (glob)
3 a
got lock after * seconds (glob)
3 a
$ cd ..
$ cp backup.hgrc $HGRCPATH
# Update one bookmark but not the other
$ cat >> $TESTTMP/inspectsql.py <<EOF
> import os, sys
> from mercurial import demandimport, extensions
> with demandimport.deactivated():
> import mysql.connector
> watchstrings = os.environ.get("INSPECTSQL")
> if watchstrings:
> watchstrings = watchstrings.split(',')
> def printsql(orig, *args, **kwargs):
> if not watchstrings or any(s for s in watchstrings if s in args[1]):
> print >> sys.stderr, args[1] % args[2]
> return orig(*args, **kwargs)
> extensions.wrapfunction(mysql.connector.cursor.MySQLCursor, "execute", printsql)
> EOF
$ cat >> $HGRCPATH <<EOF
> [extensions]
> inspectsql=$TESTTMP/inspectsql.py
> EOF
$ cd master
$ INSPECTSQL=DELETE,INSERT hg book mybook2
[hgsql] got lock after * seconds (glob)
INSERT INTO revision_references(repo, namespace, name, value) VALUES (masterrepo, 'bookmarks', mybook2, 0000000000000000000000000000000000000000)
INSERT INTO revision_references(repo, namespace, name, value) VALUES(masterrepo, 'tip', 'tip', 3) ON DUPLICATE KEY UPDATE value=3
[hgsql] held lock for * seconds (glob)
$ cd ..
$ cp backup.hgrc $HGRCPATH