comparison mercurial/dirstate.py @ 48793:6e559391f96e

tracked-key: remove the dual write and rename to tracked-hint The dual-write approach was mostly useless. As explained in the previous version of the help, the key had to be read twice before we could cache a value. However this "read twice" limitation actually also apply to any usage of the key. If some operation wants to rely of the "same value == same tracked set" property it would need to read the value before, and after running that operation (or at least, after, in all cases). So it cannot be sure the operation it did is "valid" until checking the key after the operation. As a resultat such operation can only be read-only or rollbackable. This reduce the utility of the "same value == same tracked set" a lot. So it seems simpler to drop the double write and to update the documentation to highlight that this file does not garantee race-free operation. As a result the "key" is demoted to a "hint". Documentation is updated accordingly. Differential Revision: https://phab.mercurial-scm.org/D12201
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Thu, 17 Feb 2022 07:34:49 +0100
parents 5ba24e886cec
children 6000f5b25c9b
comparison
equal deleted inserted replaced
48792:8bbb1abb9d19 48793:6e559391f96e
99 root, 99 root,
100 validate, 100 validate,
101 sparsematchfn, 101 sparsematchfn,
102 nodeconstants, 102 nodeconstants,
103 use_dirstate_v2, 103 use_dirstate_v2,
104 use_tracked_key=False, 104 use_tracked_hint=False,
105 ): 105 ):
106 """Create a new dirstate object. 106 """Create a new dirstate object.
107 107
108 opener is an open()-like callable that can be used to open the 108 opener is an open()-like callable that can be used to open the
109 dirstate file; root is the root of the directory tracked by 109 dirstate file; root is the root of the directory tracked by
110 the dirstate. 110 the dirstate.
111 """ 111 """
112 self._use_dirstate_v2 = use_dirstate_v2 112 self._use_dirstate_v2 = use_dirstate_v2
113 self._use_tracked_key = use_tracked_key 113 self._use_tracked_hint = use_tracked_hint
114 self._nodeconstants = nodeconstants 114 self._nodeconstants = nodeconstants
115 self._opener = opener 115 self._opener = opener
116 self._validate = validate 116 self._validate = validate
117 self._root = root 117 self._root = root
118 self._sparsematchfn = sparsematchfn 118 self._sparsematchfn = sparsematchfn
125 self._dirty_tracked_set = False 125 self._dirty_tracked_set = False
126 self._ui = ui 126 self._ui = ui
127 self._filecache = {} 127 self._filecache = {}
128 self._parentwriters = 0 128 self._parentwriters = 0
129 self._filename = b'dirstate' 129 self._filename = b'dirstate'
130 self._filename_tk = b'dirstate-tracked-key' 130 self._filename_th = b'dirstate-tracked-hint'
131 self._pendingfilename = b'%s.pending' % self._filename 131 self._pendingfilename = b'%s.pending' % self._filename
132 self._plchangecallbacks = {} 132 self._plchangecallbacks = {}
133 self._origpl = None 133 self._origpl = None
134 self._mapcls = dirstatemap.dirstatemap 134 self._mapcls = dirstatemap.dirstatemap
135 # Access and cache cwd early, so we don't access it for the first time 135 # Access and cache cwd early, so we don't access it for the first time
719 719
720 def write(self, tr): 720 def write(self, tr):
721 if not self._dirty: 721 if not self._dirty:
722 return 722 return
723 723
724 write_key = self._use_tracked_key and self._dirty_tracked_set 724 write_key = self._use_tracked_hint and self._dirty_tracked_set
725 if tr: 725 if tr:
726 # delay writing in-memory changes out 726 # delay writing in-memory changes out
727 if write_key:
728 tr.addfilegenerator(
729 b'dirstate-0-key-pre',
730 (self._filename_tk,),
731 lambda f: self._write_tracked_key(tr, f),
732 location=b'plain',
733 post_finalize=True,
734 )
735 tr.addfilegenerator( 727 tr.addfilegenerator(
736 b'dirstate-1-main', 728 b'dirstate-1-main',
737 (self._filename,), 729 (self._filename,),
738 lambda f: self._writedirstate(tr, f), 730 lambda f: self._writedirstate(tr, f),
739 location=b'plain', 731 location=b'plain',
740 post_finalize=True, 732 post_finalize=True,
741 ) 733 )
742 if write_key: 734 if write_key:
743 tr.addfilegenerator( 735 tr.addfilegenerator(
744 b'dirstate-2-key-post', 736 b'dirstate-2-key-post',
745 (self._filename_tk,), 737 (self._filename_th,),
746 lambda f: self._write_tracked_key(tr, f), 738 lambda f: self._write_tracked_hint(tr, f),
747 location=b'plain', 739 location=b'plain',
748 post_finalize=True, 740 post_finalize=True,
749 ) 741 )
750 return 742 return
751 743
752 file = lambda f: self._opener(f, b"w", atomictemp=True, checkambig=True) 744 file = lambda f: self._opener(f, b"w", atomictemp=True, checkambig=True)
753 if write_key:
754 # we change the key-file before changing the dirstate to make sure
755 # reading invalidate there cache before we start writing
756 with file(self._filename_tk) as f:
757 self._write_tracked_key(tr, f)
758 with file(self._filename) as f: 745 with file(self._filename) as f:
759 self._writedirstate(tr, f) 746 self._writedirstate(tr, f)
760 if write_key: 747 if write_key:
761 # we update the key-file after writing to make sure reader have a 748 # we update the key-file after writing to make sure reader have a
762 # key that match the newly written content 749 # key that match the newly written content
763 with file(self._filename_tk) as f: 750 with file(self._filename_th) as f:
764 self._write_tracked_key(tr, f) 751 self._write_tracked_hint(tr, f)
765 752
766 def delete_tracked_key(self): 753 def delete_tracked_hint(self):
767 """remove the tracked_key file 754 """remove the tracked_hint file
768 755
769 To be used by format downgrades operation""" 756 To be used by format downgrades operation"""
770 self._opener.unlink(self._filename_tk) 757 self._opener.unlink(self._filename_th)
771 self._use_tracked_key = False 758 self._use_tracked_hint = False
772 759
773 def addparentchangecallback(self, category, callback): 760 def addparentchangecallback(self, category, callback):
774 """add a callback to be called when the wd parents are changed 761 """add a callback to be called when the wd parents are changed
775 762
776 Callback will be called with the following arguments: 763 Callback will be called with the following arguments:
791 self._origpl = None 778 self._origpl = None
792 self._map.write(tr, st) 779 self._map.write(tr, st)
793 self._dirty = False 780 self._dirty = False
794 self._dirty_tracked_set = False 781 self._dirty_tracked_set = False
795 782
796 def _write_tracked_key(self, tr, f): 783 def _write_tracked_hint(self, tr, f):
797 key = node.hex(uuid.uuid4().bytes) 784 key = node.hex(uuid.uuid4().bytes)
798 f.write(b"1\n%s\n" % key) # 1 is the format version 785 f.write(b"1\n%s\n" % key) # 1 is the format version
799 786
800 def _dirignore(self, f): 787 def _dirignore(self, f):
801 if self._ignore(f): 788 if self._ignore(f):