365 default_compression_header, |
365 default_compression_header, |
366 ): |
366 ): |
367 self.opener = opener |
367 self.opener = opener |
368 self.index = index |
368 self.index = index |
369 |
369 |
370 self.__index_file = index_file |
370 self.index_file = index_file |
371 self.data_file = data_file |
371 self.data_file = data_file |
372 self.sidedata_file = sidedata_file |
372 self.sidedata_file = sidedata_file |
373 self.inline = inline |
373 self.inline = inline |
374 self.data_config = data_config |
374 self.data_config = data_config |
375 self.delta_config = delta_config |
375 self.delta_config = delta_config |
413 self.data_config.uncompressed_cache_count, |
413 self.data_config.uncompressed_cache_count, |
414 maxcost=65536, # some arbitrary initial value |
414 maxcost=65536, # some arbitrary initial value |
415 ) |
415 ) |
416 |
416 |
417 self._delay_buffer = None |
417 self._delay_buffer = None |
418 |
|
419 @property |
|
420 def index_file(self): |
|
421 return self.__index_file |
|
422 |
|
423 @index_file.setter |
|
424 def index_file(self, new_index_file): |
|
425 self.__index_file = new_index_file |
|
426 if self.inline: |
|
427 self._segmentfile.filename = new_index_file |
|
428 |
418 |
429 def __len__(self): |
419 def __len__(self): |
430 return len(self.index) |
420 return len(self.index) |
431 |
421 |
432 def clear_cache(self): |
422 def clear_cache(self): |
650 @contextlib.contextmanager |
640 @contextlib.contextmanager |
651 def reading(self): |
641 def reading(self): |
652 """Context manager that keeps data and sidedata files open for reading""" |
642 """Context manager that keeps data and sidedata files open for reading""" |
653 if len(self.index) == 0: |
643 if len(self.index) == 0: |
654 yield # nothing to be read |
644 yield # nothing to be read |
|
645 elif self._delay_buffer is not None and self.inline: |
|
646 msg = "revlog with delayed write should not be inline" |
|
647 raise error.ProgrammingError(msg) |
655 else: |
648 else: |
656 with self._segmentfile.reading(): |
649 with self._segmentfile.reading(): |
657 with self._segmentfile_sidedata.reading(): |
650 with self._segmentfile_sidedata.reading(): |
658 yield |
651 yield |
659 |
652 |
1135 sdfh.write(sidedata) |
1128 sdfh.write(sidedata) |
1136 if self._delay_buffer is None: |
1129 if self._delay_buffer is None: |
1137 ifh.write(entry) |
1130 ifh.write(entry) |
1138 else: |
1131 else: |
1139 self._delay_buffer.append(entry) |
1132 self._delay_buffer.append(entry) |
|
1133 elif self._delay_buffer is not None: |
|
1134 msg = b'invalid delayed write on inline revlog' |
|
1135 raise error.ProgrammingError(msg) |
1140 else: |
1136 else: |
1141 offset += curr * self.index.entry_size |
1137 offset += curr * self.index.entry_size |
1142 transaction.add(self.canonical_index_file, offset) |
1138 transaction.add(self.canonical_index_file, offset) |
1143 assert not sidedata |
1139 assert not sidedata |
1144 if self._delay_buffer is None: |
1140 ifh.write(entry) |
1145 ifh.write(entry) |
1141 ifh.write(data[0]) |
1146 ifh.write(data[0]) |
1142 ifh.write(data[1]) |
1147 ifh.write(data[1]) |
|
1148 else: |
|
1149 self._delay_buffer.append(entry) |
|
1150 self._delay_buffer.append(data[0]) |
|
1151 self._delay_buffer.append(data[1]) |
|
1152 return ( |
1143 return ( |
1153 ifh.tell(), |
1144 ifh.tell(), |
1154 dfh.tell() if dfh else None, |
1145 dfh.tell() if dfh else None, |
1155 sdfh.tell() if sdfh else None, |
1146 sdfh.tell() if sdfh else None, |
1156 ) |
1147 ) |
1158 def _divert_index(self): |
1149 def _divert_index(self): |
1159 return self.index_file + b'.a' |
1150 return self.index_file + b'.a' |
1160 |
1151 |
1161 def delay(self): |
1152 def delay(self): |
1162 assert not self.is_open |
1153 assert not self.is_open |
|
1154 if self.inline: |
|
1155 msg = "revlog with delayed write should not be inline" |
|
1156 raise error.ProgrammingError(msg) |
1163 if self._delay_buffer is not None or self._orig_index_file is not None: |
1157 if self._delay_buffer is not None or self._orig_index_file is not None: |
1164 # delay or divert already in place |
1158 # delay or divert already in place |
1165 return None |
1159 return None |
1166 elif len(self.index) == 0: |
1160 elif len(self.index) == 0: |
1167 self._orig_index_file = self.index_file |
1161 self._orig_index_file = self.index_file |
1171 if self.opener.exists(self.index_file): |
1165 if self.opener.exists(self.index_file): |
1172 self.opener.unlink(self.index_file) |
1166 self.opener.unlink(self.index_file) |
1173 return self.index_file |
1167 return self.index_file |
1174 else: |
1168 else: |
1175 self._delay_buffer = [] |
1169 self._delay_buffer = [] |
1176 if self.inline: |
|
1177 self._segmentfile._delay_buffer = self._delay_buffer |
|
1178 return None |
1170 return None |
1179 |
1171 |
1180 def write_pending(self): |
1172 def write_pending(self): |
1181 assert not self.is_open |
1173 assert not self.is_open |
|
1174 if self.inline: |
|
1175 msg = "revlog with delayed write should not be inline" |
|
1176 raise error.ProgrammingError(msg) |
1182 if self._orig_index_file is not None: |
1177 if self._orig_index_file is not None: |
1183 return None, True |
1178 return None, True |
1184 any_pending = False |
1179 any_pending = False |
1185 pending_index_file = self._divert_index() |
1180 pending_index_file = self._divert_index() |
1186 if self.opener.exists(pending_index_file): |
1181 if self.opener.exists(pending_index_file): |
1193 with self.opener(pending_index_file, b'r+') as ifh: |
1188 with self.opener(pending_index_file, b'r+') as ifh: |
1194 ifh.seek(0, os.SEEK_END) |
1189 ifh.seek(0, os.SEEK_END) |
1195 ifh.write(b"".join(self._delay_buffer)) |
1190 ifh.write(b"".join(self._delay_buffer)) |
1196 any_pending = True |
1191 any_pending = True |
1197 self._delay_buffer = None |
1192 self._delay_buffer = None |
1198 if self.inline: |
|
1199 self._segmentfile._delay_buffer = self._delay_buffer |
|
1200 else: |
|
1201 assert self._segmentfile._delay_buffer is None |
|
1202 self._orig_index_file = self.index_file |
1193 self._orig_index_file = self.index_file |
1203 self.index_file = pending_index_file |
1194 self.index_file = pending_index_file |
1204 return self.index_file, any_pending |
1195 return self.index_file, any_pending |
1205 |
1196 |
1206 def finalize_pending(self): |
1197 def finalize_pending(self): |
1207 assert not self.is_open |
1198 assert not self.is_open |
|
1199 if self.inline: |
|
1200 msg = "revlog with delayed write should not be inline" |
|
1201 raise error.ProgrammingError(msg) |
1208 |
1202 |
1209 delay = self._delay_buffer is not None |
1203 delay = self._delay_buffer is not None |
1210 divert = self._orig_index_file is not None |
1204 divert = self._orig_index_file is not None |
1211 |
1205 |
1212 if delay and divert: |
1206 if delay and divert: |
1214 elif delay: |
1208 elif delay: |
1215 if self._delay_buffer: |
1209 if self._delay_buffer: |
1216 with self.opener(self.index_file, b'r+') as ifh: |
1210 with self.opener(self.index_file, b'r+') as ifh: |
1217 ifh.seek(0, os.SEEK_END) |
1211 ifh.seek(0, os.SEEK_END) |
1218 ifh.write(b"".join(self._delay_buffer)) |
1212 ifh.write(b"".join(self._delay_buffer)) |
1219 self._segmentfile._delay_buffer = self._delay_buffer = None |
1213 self._delay_buffer = None |
1220 elif divert: |
1214 elif divert: |
1221 if self.opener.exists(self.index_file): |
1215 if self.opener.exists(self.index_file): |
1222 self.opener.rename( |
1216 self.opener.rename( |
1223 self.index_file, |
1217 self.index_file, |
1224 self._orig_index_file, |
1218 self._orig_index_file, |
2829 revlog has grown too large to be an inline revlog, it will convert it |
2823 revlog has grown too large to be an inline revlog, it will convert it |
2830 to use multiple index and data files. |
2824 to use multiple index and data files. |
2831 """ |
2825 """ |
2832 tiprev = len(self) - 1 |
2826 tiprev = len(self) - 1 |
2833 total_size = self.start(tiprev) + self.length(tiprev) |
2827 total_size = self.start(tiprev) + self.length(tiprev) |
2834 if not self._inline or total_size < _maxinline: |
2828 if not self._inline or (self._may_inline and total_size < _maxinline): |
2835 return |
2829 return |
2836 |
2830 |
2837 if self._docket is not None: |
2831 if self._docket is not None: |
2838 msg = b"inline revlog should not have a docket" |
2832 msg = b"inline revlog should not have a docket" |
2839 raise error.ProgrammingError(msg) |
2833 raise error.ProgrammingError(msg) |