@@ -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 );
@@ -3743,7 +3745,12 @@ mark_work_done(ArchiveHandle *AH, TocEntry *ready_list,
3743
3745
/*
3744
3746
* Process the dependency information into a form useful for parallel restore.
3745
3747
*
3746
- * We set up depCount fields that are the number of as-yet-unprocessed
3748
+ * This function takes care of fixing up some missing or badly designed
3749
+ * dependencies, and then prepares subsidiary data structures that will be
3750
+ * used in the main parallel-restore logic, including:
3751
+ * 1. We build the tocsByDumpId[] index array.
3752
+ * 2. We build the revDeps[] arrays of incoming dependency dumpIds.
3753
+ * 3. We set up depCount fields that are the number of as-yet-unprocessed
3747
3754
* dependencies for each TOC entry.
3748
3755
*
3749
3756
* We also identify locking dependencies so that we can avoid trying to
@@ -3752,29 +3759,29 @@ mark_work_done(ArchiveHandle *AH, TocEntry *ready_list,
3752
3759
static void
3753
3760
fix_dependencies (ArchiveHandle * AH )
3754
3761
{
3755
- TocEntry * * tocsByDumpId ;
3756
3762
TocEntry * te ;
3757
- DumpId maxDumpId ;
3758
3763
int i ;
3759
3764
3760
3765
/*
3761
- * For some of the steps here, it is convenient to have an array that
3762
- * indexes the TOC entries by dump ID, rather than searching the TOC list
3763
- * repeatedly. Entries for dump IDs not present in the TOC will be NULL.
3766
+ * It is convenient to have an array that indexes the TOC entries by dump
3767
+ * ID, rather than searching the TOC list repeatedly. Entries for dump
3768
+ * IDs not present in the TOC will be NULL.
3764
3769
*
3765
3770
* NOTE: because maxDumpId is just the highest dump ID defined in the
3766
3771
* archive, there might be dependencies for IDs > maxDumpId. All uses of
3767
3772
* this array must guard against out-of-range dependency numbers.
3768
3773
*
3769
- * Also, initialize the depCount fields, and make sure all the TOC items
3770
- * are marked as not being in any parallel-processing list.
3774
+ * Also, initialize the depCount/revDeps/nRevDeps fields, and make sure
3775
+ * the TOC items are marked as not being in any parallel-processing list.
3771
3776
*/
3772
3777
maxDumpId = AH -> maxDumpId ;
3773
3778
tocsByDumpId = (TocEntry * * ) calloc (maxDumpId , sizeof (TocEntry * ));
3774
3779
for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
3775
3780
{
3776
3781
tocsByDumpId [te -> dumpId - 1 ] = te ;
3777
3782
te -> depCount = te -> nDeps ;
3783
+ te -> revDeps = NULL ;
3784
+ te -> nRevDeps = 0 ;
3778
3785
te -> par_prev = NULL ;
3779
3786
te -> par_next = NULL ;
3780
3787
}
@@ -3792,6 +3799,9 @@ fix_dependencies(ArchiveHandle *AH)
3792
3799
* TABLE, if possible. However, if the dependency isn't in the archive
3793
3800
* then just assume it was a TABLE; this is to cover cases where the table
3794
3801
* was suppressed but we have the data and some dependent post-data items.
3802
+ *
3803
+ * XXX this is O(N^2) if there are a lot of tables. We ought to fix
3804
+ * pg_dump to produce correctly-linked dependencies in the first place.
3795
3805
*/
3796
3806
for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
3797
3807
{
@@ -3838,31 +3848,67 @@ fix_dependencies(ArchiveHandle *AH)
3838
3848
}
3839
3849
3840
3850
/*
3841
- * It is possible that the dependencies list items that are not in the
3842
- * archive at all. Subtract such items from the depCounts.
3851
+ * At this point we start to build the revDeps reverse-dependency arrays,
3852
+ * so all changes of dependencies must be complete.
3853
+ */
3854
+
3855
+ /*
3856
+ * Count the incoming dependencies for each item. Also, it is possible
3857
+ * that the dependencies list items that are not in the archive at
3858
+ * all. Subtract such items from the depCounts.
3843
3859
*/
3844
3860
for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
3845
3861
{
3846
3862
for (i = 0 ; i < te -> nDeps ; i ++ )
3847
3863
{
3848
3864
DumpId depid = te -> dependencies [i ];
3849
3865
3850
- if (depid > maxDumpId || tocsByDumpId [depid - 1 ] == NULL )
3866
+ if (depid <= maxDumpId && tocsByDumpId [depid - 1 ] != NULL )
3867
+ tocsByDumpId [depid - 1 ]-> nRevDeps ++ ;
3868
+ else
3851
3869
te -> depCount -- ;
3852
3870
}
3853
3871
}
3854
3872
3873
+ /*
3874
+ * Allocate space for revDeps[] arrays, and reset nRevDeps so we can
3875
+ * use it as a counter below.
3876
+ */
3877
+ for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
3878
+ {
3879
+ if (te -> nRevDeps > 0 )
3880
+ te -> revDeps = (DumpId * ) malloc (te -> nRevDeps * sizeof (DumpId ));
3881
+ te -> nRevDeps = 0 ;
3882
+ }
3883
+
3884
+ /*
3885
+ * Build the revDeps[] arrays of incoming-dependency dumpIds. This
3886
+ * had better agree with the loops above.
3887
+ */
3888
+ for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
3889
+ {
3890
+ for (i = 0 ; i < te -> nDeps ; i ++ )
3891
+ {
3892
+ DumpId depid = te -> dependencies [i ];
3893
+
3894
+ if (depid <= maxDumpId && tocsByDumpId [depid - 1 ] != NULL )
3895
+ {
3896
+ TocEntry * otherte = tocsByDumpId [depid - 1 ];
3897
+
3898
+ otherte -> revDeps [otherte -> nRevDeps ++ ] = te -> dumpId ;
3899
+ }
3900
+ }
3901
+ }
3902
+
3855
3903
/*
3856
3904
* Lastly, work out the locking dependencies.
3857
3905
*/
3858
3906
for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
3859
3907
{
3860
3908
te -> lockDeps = NULL ;
3861
3909
te -> nLockDeps = 0 ;
3862
- identify_locking_dependencies (te , tocsByDumpId , maxDumpId );
3910
+ identify_locking_dependencies (te );
3863
3911
}
3864
-
3865
- free (tocsByDumpId );
3866
3912
}
3867
3913
3868
3914
/*
@@ -3896,13 +3942,9 @@ repoint_table_dependencies(ArchiveHandle *AH,
3896
3942
* Identify which objects we'll need exclusive lock on in order to restore
3897
3943
* the given TOC entry (*other* than the one identified by the TOC entry
3898
3944
* itself). Record their dump IDs in the entry's lockDeps[] array.
3899
- * tocsByDumpId[] is a convenience array (of size maxDumpId) to avoid
3900
- * searching the TOC for each dependency.
3901
3945
*/
3902
3946
static void
3903
- identify_locking_dependencies (TocEntry * te ,
3904
- TocEntry * * tocsByDumpId ,
3905
- DumpId maxDumpId )
3947
+ identify_locking_dependencies (TocEntry * te )
3906
3948
{
3907
3949
DumpId * lockids ;
3908
3950
int nlockids ;
@@ -3956,31 +3998,21 @@ identify_locking_dependencies(TocEntry *te,
3956
3998
static void
3957
3999
reduce_dependencies (ArchiveHandle * AH , TocEntry * te , TocEntry * ready_list )
3958
4000
{
3959
- DumpId target = te -> dumpId ;
3960
4001
int i ;
3961
4002
3962
- ahlog (AH , 2 , "reducing dependencies for %d\n" , target );
4003
+ ahlog (AH , 2 , "reducing dependencies for %d\n" , te -> dumpId );
3963
4004
3964
- /*
3965
- * We must examine all entries, not only the ones after the target item,
3966
- * because if the user used a -L switch then the original dependency-
3967
- * respecting order has been destroyed by SortTocFromFile.
3968
- */
3969
- for (te = AH -> toc -> next ; te != AH -> toc ; te = te -> next )
4005
+ for (i = 0 ; i < te -> nRevDeps ; i ++ )
3970
4006
{
3971
- for (i = 0 ; i < te -> nDeps ; i ++ )
4007
+ TocEntry * otherte = tocsByDumpId [te -> revDeps [i ] - 1 ];
4008
+
4009
+ otherte -> depCount -- ;
4010
+ if (otherte -> depCount == 0 && otherte -> par_prev != NULL )
3972
4011
{
3973
- if (te -> dependencies [i ] == target )
3974
- {
3975
- te -> depCount -- ;
3976
- if (te -> depCount == 0 && te -> par_prev != NULL )
3977
- {
3978
- /* It must be in the pending list, so remove it ... */
3979
- par_list_remove (te );
3980
- /* ... and add to ready_list */
3981
- par_list_append (ready_list , te );
3982
- }
3983
- }
4012
+ /* It must be in the pending list, so remove it ... */
4013
+ par_list_remove (otherte );
4014
+ /* ... and add to ready_list */
4015
+ par_list_append (ready_list , otherte );
3984
4016
}
3985
4017
}
3986
4018
}
0 commit comments