mercurial/revlog.py
changeset 51179 a93e52f0b6ff
parent 51178 dcaa2df1f688
child 51187 6ec8387eb0be
equal deleted inserted replaced
51178:dcaa2df1f688 51179:a93e52f0b6ff
   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)