43 docket.tip_rev = tip_rev |
44 docket.tip_rev = tip_rev |
44 docket.data_length = data_length |
45 docket.data_length = data_length |
45 docket.data_unused = data_unused |
46 docket.data_unused = data_unused |
46 |
47 |
47 filename = _rawdata_filepath(revlog, docket) |
48 filename = _rawdata_filepath(revlog, docket) |
48 data = revlog.opener.tryread(filename) |
49 use_mmap = revlog.opener.options.get("exp-persistent-nodemap.mmap") |
|
50 try: |
|
51 with revlog.opener(filename) as fd: |
|
52 if use_mmap: |
|
53 data = util.buffer(util.mmapread(fd, data_length)) |
|
54 else: |
|
55 data = fd.read(data_length) |
|
56 except OSError as e: |
|
57 if e.errno != errno.ENOENT: |
|
58 raise |
49 if len(data) < data_length: |
59 if len(data) < data_length: |
50 return None |
60 return None |
51 elif len(data) > data_length: |
|
52 data = data[:data_length] |
|
53 return docket, data |
61 return docket, data |
54 |
62 |
55 |
63 |
56 def setup_persistent_nodemap(tr, revlog): |
64 def setup_persistent_nodemap(tr, revlog): |
57 """Install whatever is needed transaction side to persist a nodemap on disk |
65 """Install whatever is needed transaction side to persist a nodemap on disk |
79 msg = "calling persist nodemap on a revlog without the feature enableb" |
87 msg = "calling persist nodemap on a revlog without the feature enableb" |
80 raise error.ProgrammingError(msg) |
88 raise error.ProgrammingError(msg) |
81 |
89 |
82 can_incremental = util.safehasattr(revlog.index, "nodemap_data_incremental") |
90 can_incremental = util.safehasattr(revlog.index, "nodemap_data_incremental") |
83 ondisk_docket = revlog._nodemap_docket |
91 ondisk_docket = revlog._nodemap_docket |
|
92 feed_data = util.safehasattr(revlog.index, "update_nodemap_data") |
|
93 use_mmap = revlog.opener.options.get("exp-persistent-nodemap.mmap") |
84 |
94 |
85 data = None |
95 data = None |
86 # first attemp an incremental update of the data |
96 # first attemp an incremental update of the data |
87 if can_incremental and ondisk_docket is not None: |
97 if can_incremental and ondisk_docket is not None: |
88 target_docket = revlog._nodemap_docket.copy() |
98 target_docket = revlog._nodemap_docket.copy() |
95 data = None |
105 data = None |
96 else: |
106 else: |
97 datafile = _rawdata_filepath(revlog, target_docket) |
107 datafile = _rawdata_filepath(revlog, target_docket) |
98 # EXP-TODO: if this is a cache, this should use a cache vfs, not a |
108 # EXP-TODO: if this is a cache, this should use a cache vfs, not a |
99 # store vfs |
109 # store vfs |
|
110 new_length = target_docket.data_length + len(data) |
100 with revlog.opener(datafile, b'r+') as fd: |
111 with revlog.opener(datafile, b'r+') as fd: |
101 fd.seek(target_docket.data_length) |
112 fd.seek(target_docket.data_length) |
102 fd.write(data) |
113 fd.write(data) |
103 fd.seek(0) |
114 if feed_data: |
104 new_data = fd.read(target_docket.data_length + len(data)) |
115 if use_mmap: |
105 target_docket.data_length += len(data) |
116 fd.seek(0) |
|
117 new_data = fd.read(new_length) |
|
118 else: |
|
119 fd.flush() |
|
120 new_data = util.buffer(util.mmapread(fd, new_length)) |
|
121 target_docket.data_length = new_length |
106 target_docket.data_unused += data_changed_count |
122 target_docket.data_unused += data_changed_count |
107 |
123 |
108 if data is None: |
124 if data is None: |
109 # otherwise fallback to a full new export |
125 # otherwise fallback to a full new export |
110 target_docket = NodeMapDocket() |
126 target_docket = NodeMapDocket() |
113 data = revlog.index.nodemap_data_all() |
129 data = revlog.index.nodemap_data_all() |
114 else: |
130 else: |
115 data = persistent_data(revlog.index) |
131 data = persistent_data(revlog.index) |
116 # EXP-TODO: if this is a cache, this should use a cache vfs, not a |
132 # EXP-TODO: if this is a cache, this should use a cache vfs, not a |
117 # store vfs |
133 # store vfs |
118 new_data = data |
134 with revlog.opener(datafile, b'w+') as fd: |
119 with revlog.opener(datafile, b'w') as fd: |
|
120 fd.write(data) |
135 fd.write(data) |
|
136 if feed_data: |
|
137 if use_mmap: |
|
138 new_data = data |
|
139 else: |
|
140 fd.flush() |
|
141 new_data = util.buffer(util.mmapread(fd, len(data))) |
121 target_docket.data_length = len(data) |
142 target_docket.data_length = len(data) |
122 target_docket.tip_rev = revlog.tiprev() |
143 target_docket.tip_rev = revlog.tiprev() |
123 # EXP-TODO: if this is a cache, this should use a cache vfs, not a |
144 # EXP-TODO: if this is a cache, this should use a cache vfs, not a |
124 # store vfs |
145 # store vfs |
125 with revlog.opener(revlog.nodemap_file, b'w', atomictemp=True) as fp: |
146 with revlog.opener(revlog.nodemap_file, b'w', atomictemp=True) as fp: |
126 fp.write(target_docket.serialize()) |
147 fp.write(target_docket.serialize()) |
127 revlog._nodemap_docket = target_docket |
148 revlog._nodemap_docket = target_docket |
128 if util.safehasattr(revlog.index, "update_nodemap_data"): |
149 if feed_data: |
129 revlog.index.update_nodemap_data(target_docket, new_data) |
150 revlog.index.update_nodemap_data(target_docket, new_data) |
130 |
151 |
131 # EXP-TODO: if the transaction abort, we should remove the new data and |
152 # EXP-TODO: if the transaction abort, we should remove the new data and |
132 # reinstall the old one. |
153 # reinstall the old one. |
133 |
154 |