88#include "sha1-lookup.h"
99#include "midx.h"
1010#include "progress.h"
11+ #include "trace2.h"
1112
1213#define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
1314#define MIDX_VERSION 1
@@ -164,6 +165,9 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
164165 m -> pack_names [i ]);
165166 }
166167
168+ trace2_data_intmax ("midx" , the_repository , "load/num_packs" , m -> num_packs );
169+ trace2_data_intmax ("midx" , the_repository , "load/num_objects" , m -> num_objects );
170+
167171 return m ;
168172
169173cleanup_fail :
@@ -958,8 +962,35 @@ static void midx_report(const char *fmt, ...)
958962 va_end (ap );
959963}
960964
965+ struct pair_pos_vs_id
966+ {
967+ uint32_t pos ;
968+ uint32_t pack_int_id ;
969+ };
970+
971+ static int compare_pair_pos_vs_id (const void * _a , const void * _b )
972+ {
973+ struct pair_pos_vs_id * a = (struct pair_pos_vs_id * )_a ;
974+ struct pair_pos_vs_id * b = (struct pair_pos_vs_id * )_b ;
975+
976+ return b -> pack_int_id - a -> pack_int_id ;
977+ }
978+
979+ /*
980+ * Limit calls to display_progress() for performance reasons.
981+ * The interval here was arbitrarily chosen.
982+ */
983+ #define SPARSE_PROGRESS_INTERVAL (1 << 12)
984+ #define midx_display_sparse_progress (progress , n ) \
985+ do { \
986+ uint64_t _n = (n); \
987+ if ((_n & (SPARSE_PROGRESS_INTERVAL - 1)) == 0) \
988+ display_progress(progress, _n); \
989+ } while (0)
990+
961991int verify_midx_file (const char * object_dir )
962992{
993+ struct pair_pos_vs_id * pairs = NULL ;
963994 uint32_t i ;
964995 struct progress * progress ;
965996 struct multi_pack_index * m = load_multi_pack_index (object_dir , 1 );
@@ -968,10 +999,15 @@ int verify_midx_file(const char *object_dir)
968999 if (!m )
9691000 return 0 ;
9701001
1002+ progress = start_progress (_ ("Looking for referenced packfiles" ),
1003+ m -> num_packs );
9711004 for (i = 0 ; i < m -> num_packs ; i ++ ) {
9721005 if (prepare_midx_pack (m , i ))
9731006 midx_report ("failed to load pack in position %d" , i );
1007+
1008+ display_progress (progress , i + 1 );
9741009 }
1010+ stop_progress (& progress );
9751011
9761012 for (i = 0 ; i < 255 ; i ++ ) {
9771013 uint32_t oid_fanout1 = ntohl (m -> chunk_oid_fanout [i ]);
@@ -982,6 +1018,8 @@ int verify_midx_file(const char *object_dir)
9821018 i , oid_fanout1 , oid_fanout2 , i + 1 );
9831019 }
9841020
1021+ progress = start_sparse_progress (_ ("Verifying OID order in MIDX" ),
1022+ m -> num_objects - 1 );
9851023 for (i = 0 ; i < m -> num_objects - 1 ; i ++ ) {
9861024 struct object_id oid1 , oid2 ;
9871025
@@ -991,18 +1029,47 @@ int verify_midx_file(const char *object_dir)
9911029 if (oidcmp (& oid1 , & oid2 ) >= 0 )
9921030 midx_report (_ ("oid lookup out of order: oid[%d] = %s >= %s = oid[%d]" ),
9931031 i , oid_to_hex (& oid1 ), oid_to_hex (& oid2 ), i + 1 );
1032+
1033+ midx_display_sparse_progress (progress , i + 1 );
9941034 }
1035+ stop_progress (& progress );
9951036
996- progress = start_progress (_ ("Verifying object offsets" ), m -> num_objects );
1037+ /*
1038+ * Create an array mapping each object to its packfile id. Sort it
1039+ * to group the objects by packfile. Use this permutation to visit
1040+ * each of the objects and only require 1 packfile to be open at a
1041+ * time.
1042+ */
1043+ ALLOC_ARRAY (pairs , m -> num_objects );
1044+ for (i = 0 ; i < m -> num_objects ; i ++ ) {
1045+ pairs [i ].pos = i ;
1046+ pairs [i ].pack_int_id = nth_midxed_pack_int_id (m , i );
1047+ }
1048+
1049+ progress = start_sparse_progress (_ ("Sorting objects by packfile" ),
1050+ m -> num_objects );
1051+ display_progress (progress , 0 ); /* TODO: Measure QSORT() progress */
1052+ QSORT (pairs , m -> num_objects , compare_pair_pos_vs_id );
1053+ stop_progress (& progress );
1054+
1055+ progress = start_sparse_progress (_ ("Verifying object offsets" ), m -> num_objects );
9971056 for (i = 0 ; i < m -> num_objects ; i ++ ) {
9981057 struct object_id oid ;
9991058 struct pack_entry e ;
10001059 off_t m_offset , p_offset ;
10011060
1002- nth_midxed_object_oid (& oid , m , i );
1061+ if (i > 0 && pairs [i - 1 ].pack_int_id != pairs [i ].pack_int_id &&
1062+ m -> packs [pairs [i - 1 ].pack_int_id ])
1063+ {
1064+ close_pack_fd (m -> packs [pairs [i - 1 ].pack_int_id ]);
1065+ close_pack_index (m -> packs [pairs [i - 1 ].pack_int_id ]);
1066+ }
1067+
1068+ nth_midxed_object_oid (& oid , m , pairs [i ].pos );
1069+
10031070 if (!fill_midx_entry (& oid , & e , m )) {
10041071 midx_report (_ ("failed to load pack entry for oid[%d] = %s" ),
1005- i , oid_to_hex (& oid ));
1072+ pairs [ i ]. pos , oid_to_hex (& oid ));
10061073 continue ;
10071074 }
10081075
@@ -1017,11 +1084,13 @@ int verify_midx_file(const char *object_dir)
10171084
10181085 if (m_offset != p_offset )
10191086 midx_report (_ ("incorrect object offset for oid[%d] = %s: %" PRIx64 " != %" PRIx64 ),
1020- i , oid_to_hex (& oid ), m_offset , p_offset );
1087+ pairs [ i ]. pos , oid_to_hex (& oid ), m_offset , p_offset );
10211088
1022- display_progress (progress , i + 1 );
1089+ midx_display_sparse_progress (progress , i + 1 );
10231090 }
10241091 stop_progress (& progress );
10251092
1093+ free (pairs );
1094+
10261095 return verify_midx_error ;
10271096}
0 commit comments