@@ -79,6 +79,10 @@ const char *progname;
79
79
80
80
static const char * modulename = gettext_noop ("archiver" );
81
81
82
+ /* index array created by fix_dependencies -- only used in parallel restore */
83
+ static TocEntry * * tocsByDumpId ; /* index by dumpId - 1 */
84
+ static DumpId maxDumpId ; /* length of above array */
85
+
82
86
83
87
static ArchiveHandle * _allocAH (const char * FileSpec , const ArchiveFormat fmt ,
84
88
const int compression , ArchiveMode mode );
@@ -134,9 +138,7 @@ static void fix_dependencies(ArchiveHandle *AH);
134
138
static bool has_lock_conflicts (TocEntry * te1 , TocEntry * te2 );
135
139
static void repoint_table_dependencies (ArchiveHandle * AH ,
136
140
DumpId tableId , DumpId tableDataId );
137
- static void identify_locking_dependencies (TocEntry * te ,
138
- TocEntry * * tocsByDumpId ,
139
- DumpId maxDumpId );
141
+ static void identify_locking_dependencies (TocEntry * te );
140
142
static void reduce_dependencies (ArchiveHandle * AH , TocEntry * te ,
141
143
TocEntry * ready_list );
142
144
static void mark_create_done (ArchiveHandle * AH , TocEntry * te );
@@ -3737,7 +3739,12 @@ mark_work_done(ArchiveHandle *AH, TocEntry *ready_list,
3737
3739
/*
3738
3740
* Process the dependency information into a form useful for parallel restore.
3739
3741
*
3740
- * We set up depCount fields that are the number of as-yet-unprocessed
3742
+ * This function takes care of fixing up some missing or badly designed
3743
+ * dependencies, and then prepares subsidiary data structures that will be
3744
+ * used in the main parallel-restore logic, including:
3745
+ * 1. We build the tocsByDumpId[] index array.
3746
+ * 2. We build the revDeps[] arrays of incoming dependency dumpIds.
3747
+ * 3. We set up depCount fields that are the number of as-yet-unprocessed
3741
3748
* dependencies for each TOC entry.
3742
3749
*
3743
3750
* We also identify locking dependencies so that we can avoid trying to
@@ -3746,29 +3753,29 @@ mark_work_done(ArchiveHandle *AH, TocEntry *ready_list,
3746
3753
static void
3747
3754
fix_dependencies (ArchiveHandle * AH )
3748
3755
{
3749
- TocEntry * * tocsByDumpId ;
3750
3756
TocEntry * te ;
3751
- DumpId maxDumpId ;
3752
3757
int i ;
3753
3758
3754
3759
/*
3755
- * For some of the steps here, it is convenient to have an array that
3756
- * indexes the TOC entries by dump ID, rather than searching the TOC list
3757
- * repeatedly. Entries for dump IDs not present in the TOC will be NULL.
3760
+ * It is convenient to have an array that indexes the TOC entries by dump
3761
+ * ID, rather than searching the TOC list repeatedly. Entries for dump
3762
+ * IDs not present in the TOC will be NULL.
3758
3763
*
3759
3764
* NOTE: because maxDumpId is just the highest dump ID defined in the
3760
3765
* archive, there might be dependencies for IDs > maxDumpId. All uses of
3761
3766
* this array must guard against out-of-range dependency numbers.
3762
3767
*
3763
- * Also, initialize the depCount fields, and make sure all the TOC items
3764
- * are marked as not being in any parallel-processing list.
3768
+ * Also, initialize the depCount/revDeps/nRevDeps fields, and make sure
3769
+ * the TOC items are marked as not being in any parallel-processing list.
3765
3770
*/
3766
3771
maxDumpId = AH -> maxDumpId ;
3767
3772
tocsByDumpId = (TocEntry * * ) calloc (maxDumpId , sizeof (TocEntry * ));
3768
3773
for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
3769
3774
{
3770
3775
tocsByDumpId [te -> dumpId - 1 ] = te ;
3771
3776
te -> depCount = te -> nDeps ;
3777
+ te -> revDeps = NULL ;
3778
+ te -> nRevDeps = 0 ;
3772
3779
te -> par_prev = NULL ;
3773
3780
te -> par_next = NULL ;
3774
3781
}
@@ -3786,6 +3793,9 @@ fix_dependencies(ArchiveHandle *AH)
3786
3793
* TABLE, if possible. However, if the dependency isn't in the archive
3787
3794
* then just assume it was a TABLE; this is to cover cases where the table
3788
3795
* was suppressed but we have the data and some dependent post-data items.
3796
+ *
3797
+ * XXX this is O(N^2) if there are a lot of tables. We ought to fix
3798
+ * pg_dump to produce correctly-linked dependencies in the first place.
3789
3799
*/
3790
3800
for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
3791
3801
{
@@ -3832,31 +3842,67 @@ fix_dependencies(ArchiveHandle *AH)
3832
3842
}
3833
3843
3834
3844
/*
3835
- * It is possible that the dependencies list items that are not in the
3836
- * archive at all. Subtract such items from the depCounts.
3845
+ * At this point we start to build the revDeps reverse-dependency arrays,
3846
+ * so all changes of dependencies must be complete.
3847
+ */
3848
+
3849
+ /*
3850
+ * Count the incoming dependencies for each item. Also, it is possible
3851
+ * that the dependencies list items that are not in the archive at
3852
+ * all. Subtract such items from the depCounts.
3837
3853
*/
3838
3854
for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
3839
3855
{
3840
3856
for (i = 0 ; i < te -> nDeps ; i ++ )
3841
3857
{
3842
3858
DumpId depid = te -> dependencies [i ];
3843
3859
3844
- if (depid > maxDumpId || tocsByDumpId [depid - 1 ] == NULL )
3860
+ if (depid <= maxDumpId && tocsByDumpId [depid - 1 ] != NULL )
3861
+ tocsByDumpId [depid - 1 ]-> nRevDeps ++ ;
3862
+ else
3845
3863
te -> depCount -- ;
3846
3864
}
3847
3865
}
3848
3866
3867
+ /*
3868
+ * Allocate space for revDeps[] arrays, and reset nRevDeps so we can
3869
+ * use it as a counter below.
3870
+ */
3871
+ for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
3872
+ {
3873
+ if (te -> nRevDeps > 0 )
3874
+ te -> revDeps = (DumpId * ) malloc (te -> nRevDeps * sizeof (DumpId ));
3875
+ te -> nRevDeps = 0 ;
3876
+ }
3877
+
3878
+ /*
3879
+ * Build the revDeps[] arrays of incoming-dependency dumpIds. This
3880
+ * had better agree with the loops above.
3881
+ */
3882
+ for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
3883
+ {
3884
+ for (i = 0 ; i < te -> nDeps ; i ++ )
3885
+ {
3886
+ DumpId depid = te -> dependencies [i ];
3887
+
3888
+ if (depid <= maxDumpId && tocsByDumpId [depid - 1 ] != NULL )
3889
+ {
3890
+ TocEntry * otherte = tocsByDumpId [depid - 1 ];
3891
+
3892
+ otherte -> revDeps [otherte -> nRevDeps ++ ] = te -> dumpId ;
3893
+ }
3894
+ }
3895
+ }
3896
+
3849
3897
/*
3850
3898
* Lastly, work out the locking dependencies.
3851
3899
*/
3852
3900
for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
3853
3901
{
3854
3902
te -> lockDeps = NULL ;
3855
3903
te -> nLockDeps = 0 ;
3856
- identify_locking_dependencies (te , tocsByDumpId , maxDumpId );
3904
+ identify_locking_dependencies (te );
3857
3905
}
3858
-
3859
- free (tocsByDumpId );
3860
3906
}
3861
3907
3862
3908
/*
@@ -3890,13 +3936,9 @@ repoint_table_dependencies(ArchiveHandle *AH,
3890
3936
* Identify which objects we'll need exclusive lock on in order to restore
3891
3937
* the given TOC entry (*other* than the one identified by the TOC entry
3892
3938
* itself). Record their dump IDs in the entry's lockDeps[] array.
3893
- * tocsByDumpId[] is a convenience array (of size maxDumpId) to avoid
3894
- * searching the TOC for each dependency.
3895
3939
*/
3896
3940
static void
3897
- identify_locking_dependencies (TocEntry * te ,
3898
- TocEntry * * tocsByDumpId ,
3899
- DumpId maxDumpId )
3941
+ identify_locking_dependencies (TocEntry * te )
3900
3942
{
3901
3943
DumpId * lockids ;
3902
3944
int nlockids ;
@@ -3950,31 +3992,21 @@ identify_locking_dependencies(TocEntry *te,
3950
3992
static void
3951
3993
reduce_dependencies (ArchiveHandle * AH , TocEntry * te , TocEntry * ready_list )
3952
3994
{
3953
- DumpId target = te -> dumpId ;
3954
3995
int i ;
3955
3996
3956
- ahlog (AH , 2 , "reducing dependencies for %d\n" , target );
3997
+ ahlog (AH , 2 , "reducing dependencies for %d\n" , te -> dumpId );
3957
3998
3958
- /*
3959
- * We must examine all entries, not only the ones after the target item,
3960
- * because if the user used a -L switch then the original dependency-
3961
- * respecting order has been destroyed by SortTocFromFile.
3962
- */
3963
- for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
3999
+ for (i = 0 ; i < te -> nRevDeps ; i ++ )
3964
4000
{
3965
- for (i = 0 ; i < te -> nDeps ; i ++ )
4001
+ TocEntry * otherte = tocsByDumpId [te -> revDeps [i ] - 1 ];
4002
+
4003
+ otherte -> depCount -- ;
4004
+ if (otherte -> depCount == 0 && otherte -> par_prev != NULL )
3966
4005
{
3967
- if (te -> dependencies [i ] == target )
3968
- {
3969
- te -> depCount -- ;
3970
- if (te -> depCount == 0 && te -> par_prev != NULL )
3971
- {
3972
- /* It must be in the pending list, so remove it ... */
3973
- par_list_remove (te );
3974
- /* ... and add to ready_list */
3975
- par_list_append (ready_list , te );
3976
- }
3977
- }
4006
+ /* It must be in the pending list, so remove it ... */
4007
+ par_list_remove (otherte );
4008
+ /* ... and add to ready_list */
4009
+ par_list_append (ready_list , otherte );
3978
4010
}
3979
4011
}
3980
4012
}
0 commit comments