710 fm.write(b'revlog.target', b' %s', revlog_target) |
710 fm.write(b'revlog.target', b' %s', revlog_target) |
711 |
711 |
712 fm.plain(b'\n') |
712 fm.plain(b'\n') |
713 |
713 |
714 |
714 |
715 def debug_delta_chain(revlog): |
715 class DeltaChainAuditor: |
716 r = revlog |
716 def __init__(self, revlog): |
717 index = r.index |
717 self._revlog = revlog |
718 start = r.start |
718 self._index = self._revlog.index |
719 length = r.length |
719 self._generaldelta = revlog.delta_config.general_delta |
720 generaldelta = r.delta_config.general_delta |
720 self._chain_size_cache = {} |
721 withsparseread = r.data_config.with_sparse_read |
721 # security to avoid crash on corrupted revlogs |
722 |
722 self._total_revs = len(self._index) |
723 # security to avoid crash on corrupted revlogs |
723 |
724 total_revs = len(index) |
724 def revinfo(self, rev): |
725 |
725 e = self._index[rev] |
726 chain_size_cache = {} |
|
727 |
|
728 def revinfo(rev): |
|
729 e = index[rev] |
|
730 compsize = e[constants.ENTRY_DATA_COMPRESSED_LENGTH] |
726 compsize = e[constants.ENTRY_DATA_COMPRESSED_LENGTH] |
731 uncompsize = e[constants.ENTRY_DATA_UNCOMPRESSED_LENGTH] |
727 uncompsize = e[constants.ENTRY_DATA_UNCOMPRESSED_LENGTH] |
732 |
728 |
733 base = e[constants.ENTRY_DELTA_BASE] |
729 base = e[constants.ENTRY_DELTA_BASE] |
734 p1 = e[constants.ENTRY_PARENT_1] |
730 p1 = e[constants.ENTRY_PARENT_1] |
740 # chain. |
736 # chain. |
741 # |
737 # |
742 # However we need to detect that as a special case for delta-type, that |
738 # However we need to detect that as a special case for delta-type, that |
743 # is not simply "other". |
739 # is not simply "other". |
744 p1_base = p1 |
740 p1_base = p1 |
745 if p1 != nodemod.nullrev and p1 < total_revs: |
741 if p1 != nodemod.nullrev and p1 < self._total_revs: |
746 e1 = index[p1] |
742 e1 = self._index[p1] |
747 while e1[constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0: |
743 while e1[constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0: |
748 new_base = e1[constants.ENTRY_DELTA_BASE] |
744 new_base = e1[constants.ENTRY_DELTA_BASE] |
749 if ( |
745 if ( |
750 new_base == p1_base |
746 new_base == p1_base |
751 or new_base == nodemod.nullrev |
747 or new_base == nodemod.nullrev |
752 or new_base >= total_revs |
748 or new_base >= self._total_revs |
753 ): |
749 ): |
754 break |
750 break |
755 p1_base = new_base |
751 p1_base = new_base |
756 e1 = index[p1_base] |
752 e1 = self._index[p1_base] |
757 p2_base = p2 |
753 p2_base = p2 |
758 if p2 != nodemod.nullrev and p2 < total_revs: |
754 if p2 != nodemod.nullrev and p2 < self._total_revs: |
759 e2 = index[p2] |
755 e2 = self._index[p2] |
760 while e2[constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0: |
756 while e2[constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0: |
761 new_base = e2[constants.ENTRY_DELTA_BASE] |
757 new_base = e2[constants.ENTRY_DELTA_BASE] |
762 if ( |
758 if ( |
763 new_base == p2_base |
759 new_base == p2_base |
764 or new_base == nodemod.nullrev |
760 or new_base == nodemod.nullrev |
765 or new_base >= total_revs |
761 or new_base >= self._total_revs |
766 ): |
762 ): |
767 break |
763 break |
768 p2_base = new_base |
764 p2_base = new_base |
769 e2 = index[p2_base] |
765 e2 = self._index[p2_base] |
770 |
766 |
771 if generaldelta: |
767 if self._generaldelta: |
772 if base == p1: |
768 if base == p1: |
773 deltatype = b'p1' |
769 deltatype = b'p1' |
774 elif base == p2: |
770 elif base == p2: |
775 deltatype = b'p2' |
771 deltatype = b'p2' |
776 elif base == rev: |
772 elif base == rev: |
777 deltatype = b'base' |
773 deltatype = b'base' |
778 elif base == p1_base: |
774 elif base == p1_base: |
779 deltatype = b'skip1' |
775 deltatype = b'skip1' |
780 elif base == p2_base: |
776 elif base == p2_base: |
781 deltatype = b'skip2' |
777 deltatype = b'skip2' |
782 elif r.issnapshot(rev): |
778 elif self._revlog.issnapshot(rev): |
783 deltatype = b'snap' |
779 deltatype = b'snap' |
784 elif base == rev - 1: |
780 elif base == rev - 1: |
785 deltatype = b'prev' |
781 deltatype = b'prev' |
786 else: |
782 else: |
787 deltatype = b'other' |
783 deltatype = b'other' |
789 if base == rev: |
785 if base == rev: |
790 deltatype = b'base' |
786 deltatype = b'base' |
791 else: |
787 else: |
792 deltatype = b'prev' |
788 deltatype = b'prev' |
793 |
789 |
794 chain = r._deltachain(rev)[0] |
790 chain = self._revlog._deltachain(rev)[0] |
795 chain_size = 0 |
791 chain_size = 0 |
796 for iter_rev in reversed(chain): |
792 for iter_rev in reversed(chain): |
797 cached = chain_size_cache.get(iter_rev) |
793 cached = self._chain_size_cache.get(iter_rev) |
798 if cached is not None: |
794 if cached is not None: |
799 chain_size += cached |
795 chain_size += cached |
800 break |
796 break |
801 e = index[iter_rev] |
797 e = self._index[iter_rev] |
802 chain_size += e[constants.ENTRY_DATA_COMPRESSED_LENGTH] |
798 chain_size += e[constants.ENTRY_DATA_COMPRESSED_LENGTH] |
803 chain_size_cache[rev] = chain_size |
799 self._chain_size_cache[rev] = chain_size |
804 |
800 |
805 return p1, p2, compsize, uncompsize, deltatype, chain, chain_size |
801 return p1, p2, compsize, uncompsize, deltatype, chain, chain_size |
|
802 |
|
803 |
|
804 def debug_delta_chain(revlog): |
|
805 auditor = DeltaChainAuditor(revlog) |
|
806 r = revlog |
|
807 start = r.start |
|
808 length = r.length |
|
809 withsparseread = revlog.data_config.with_sparse_read |
806 |
810 |
807 header = ( |
811 header = ( |
808 b' rev p1 p2 chain# chainlen prev delta ' |
812 b' rev p1 p2 chain# chainlen prev delta ' |
809 b'size rawsize chainsize ratio lindist extradist ' |
813 b'size rawsize chainsize ratio lindist extradist ' |
810 b'extraratio' |
814 b'extraratio' |
814 header += b'\n' |
818 header += b'\n' |
815 yield header |
819 yield header |
816 |
820 |
817 chainbases = {} |
821 chainbases = {} |
818 for rev in r: |
822 for rev in r: |
819 p1, p2, comp, uncomp, deltatype, chain, chainsize = revinfo(rev) |
823 p1, p2, comp, uncomp, deltatype, chain, chainsize = auditor.revinfo(rev) |
820 chainbase = chain[0] |
824 chainbase = chain[0] |
821 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1) |
825 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1) |
822 basestart = start(chainbase) |
826 basestart = start(chainbase) |
823 revstart = start(rev) |
827 revstart = start(rev) |
824 lineardist = revstart + comp - basestart |
828 lineardist = revstart + comp - basestart |