8
8
#include "sha1-lookup.h"
9
9
#include "midx.h"
10
10
#include "progress.h"
11
+ #include "trace2.h"
11
12
12
13
#define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
13
14
#define MIDX_VERSION 1
@@ -164,6 +165,9 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
164
165
m -> pack_names [i ]);
165
166
}
166
167
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
+
167
171
return m ;
168
172
169
173
cleanup_fail :
@@ -958,8 +962,35 @@ static void midx_report(const char *fmt, ...)
958
962
va_end (ap );
959
963
}
960
964
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
+
961
991
int verify_midx_file (const char * object_dir )
962
992
{
993
+ struct pair_pos_vs_id * pairs = NULL ;
963
994
uint32_t i ;
964
995
struct progress * progress ;
965
996
struct multi_pack_index * m = load_multi_pack_index (object_dir , 1 );
@@ -968,10 +999,15 @@ int verify_midx_file(const char *object_dir)
968
999
if (!m )
969
1000
return 0 ;
970
1001
1002
+ progress = start_progress (_ ("Looking for referenced packfiles" ),
1003
+ m -> num_packs );
971
1004
for (i = 0 ; i < m -> num_packs ; i ++ ) {
972
1005
if (prepare_midx_pack (m , i ))
973
1006
midx_report ("failed to load pack in position %d" , i );
1007
+
1008
+ display_progress (progress , i + 1 );
974
1009
}
1010
+ stop_progress (& progress );
975
1011
976
1012
for (i = 0 ; i < 255 ; i ++ ) {
977
1013
uint32_t oid_fanout1 = ntohl (m -> chunk_oid_fanout [i ]);
@@ -982,6 +1018,8 @@ int verify_midx_file(const char *object_dir)
982
1018
i , oid_fanout1 , oid_fanout2 , i + 1 );
983
1019
}
984
1020
1021
+ progress = start_sparse_progress (_ ("Verifying OID order in MIDX" ),
1022
+ m -> num_objects - 1 );
985
1023
for (i = 0 ; i < m -> num_objects - 1 ; i ++ ) {
986
1024
struct object_id oid1 , oid2 ;
987
1025
@@ -991,18 +1029,47 @@ int verify_midx_file(const char *object_dir)
991
1029
if (oidcmp (& oid1 , & oid2 ) >= 0 )
992
1030
midx_report (_ ("oid lookup out of order: oid[%d] = %s >= %s = oid[%d]" ),
993
1031
i , oid_to_hex (& oid1 ), oid_to_hex (& oid2 ), i + 1 );
1032
+
1033
+ midx_display_sparse_progress (progress , i + 1 );
994
1034
}
1035
+ stop_progress (& progress );
995
1036
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 );
997
1056
for (i = 0 ; i < m -> num_objects ; i ++ ) {
998
1057
struct object_id oid ;
999
1058
struct pack_entry e ;
1000
1059
off_t m_offset , p_offset ;
1001
1060
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
+
1003
1070
if (!fill_midx_entry (& oid , & e , m )) {
1004
1071
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 ));
1006
1073
continue ;
1007
1074
}
1008
1075
@@ -1017,11 +1084,13 @@ int verify_midx_file(const char *object_dir)
1017
1084
1018
1085
if (m_offset != p_offset )
1019
1086
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 );
1021
1088
1022
- display_progress (progress , i + 1 );
1089
+ midx_display_sparse_progress (progress , i + 1 );
1023
1090
}
1024
1091
stop_progress (& progress );
1025
1092
1093
+ free (pairs );
1094
+
1026
1095
return verify_midx_error ;
1027
1096
}
0 commit comments