@@ -79,6 +79,10 @@ const char *progname;
7979
8080static const char * modulename = gettext_noop ("archiver" );
8181
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+
8286
8387static ArchiveHandle * _allocAH (const char * FileSpec ,const ArchiveFormat fmt ,
8488const int compression ,ArchiveMode mode );
@@ -134,9 +138,7 @@ static void fix_dependencies(ArchiveHandle *AH);
134138static bool has_lock_conflicts (TocEntry * te1 ,TocEntry * te2 );
135139static void repoint_table_dependencies (ArchiveHandle * AH ,
136140DumpId 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 );
140142static void reduce_dependencies (ArchiveHandle * AH ,TocEntry * te ,
141143TocEntry * ready_list );
142144static void mark_create_done (ArchiveHandle * AH ,TocEntry * te );
@@ -3743,7 +3745,12 @@ mark_work_done(ArchiveHandle *AH, TocEntry *ready_list,
37433745/*
37443746 * Process the dependency information into a form useful for parallel restore.
37453747 *
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
37473754 * dependencies for each TOC entry.
37483755 *
37493756 * We also identify locking dependencies so that we can avoid trying to
@@ -3752,29 +3759,29 @@ mark_work_done(ArchiveHandle *AH, TocEntry *ready_list,
37523759static void
37533760fix_dependencies (ArchiveHandle * AH )
37543761{
3755- TocEntry * * tocsByDumpId ;
37563762TocEntry * te ;
3757- DumpId maxDumpId ;
37583763int i ;
37593764
37603765/*
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.
37643769 *
37653770 * NOTE: because maxDumpId is just the highest dump ID defined in the
37663771 * archive, there might be dependencies for IDs > maxDumpId. All uses of
37673772 * this array must guard against out-of-range dependency numbers.
37683773 *
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.
37713776 */
37723777maxDumpId = AH -> maxDumpId ;
37733778tocsByDumpId = (TocEntry * * )calloc (maxDumpId ,sizeof (TocEntry * ));
37743779for (te = AH -> toc -> next ;te != AH -> toc ;te = te -> next )
37753780{
37763781tocsByDumpId [te -> dumpId - 1 ]= te ;
37773782te -> depCount = te -> nDeps ;
3783+ te -> revDeps = NULL ;
3784+ te -> nRevDeps = 0 ;
37783785te -> par_prev = NULL ;
37793786te -> par_next = NULL ;
37803787}
@@ -3792,6 +3799,9 @@ fix_dependencies(ArchiveHandle *AH)
37923799 * TABLE, if possible.However, if the dependency isn't in the archive
37933800 * then just assume it was a TABLE; this is to cover cases where the table
37943801 * 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.
37953805 */
37963806for (te = AH -> toc -> next ;te != AH -> toc ;te = te -> next )
37973807{
@@ -3838,31 +3848,67 @@ fix_dependencies(ArchiveHandle *AH)
38383848}
38393849
38403850/*
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.
38433859 */
38443860for (te = AH -> toc -> next ;te != AH -> toc ;te = te -> next )
38453861{
38463862for (i = 0 ;i < te -> nDeps ;i ++ )
38473863{
38483864DumpId depid = te -> dependencies [i ];
38493865
3850- if (depid > maxDumpId || tocsByDumpId [depid - 1 ]== NULL )
3866+ if (depid <=maxDumpId && tocsByDumpId [depid - 1 ]!= NULL )
3867+ tocsByDumpId [depid - 1 ]-> nRevDeps ++ ;
3868+ else
38513869te -> depCount -- ;
38523870}
38533871}
38543872
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+
38553903/*
38563904 * Lastly, work out the locking dependencies.
38573905 */
38583906for (te = AH -> toc -> next ;te != AH -> toc ;te = te -> next )
38593907{
38603908te -> lockDeps = NULL ;
38613909te -> nLockDeps = 0 ;
3862- identify_locking_dependencies (te , tocsByDumpId , maxDumpId );
3910+ identify_locking_dependencies (te );
38633911}
3864-
3865- free (tocsByDumpId );
38663912}
38673913
38683914/*
@@ -3896,13 +3942,9 @@ repoint_table_dependencies(ArchiveHandle *AH,
38963942 * Identify which objects we'll need exclusive lock on in order to restore
38973943 * the given TOC entry (*other* than the one identified by the TOC entry
38983944 * 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.
39013945 */
39023946static void
3903- identify_locking_dependencies (TocEntry * te ,
3904- TocEntry * * tocsByDumpId ,
3905- DumpId maxDumpId )
3947+ identify_locking_dependencies (TocEntry * te )
39063948{
39073949DumpId * lockids ;
39083950int nlockids ;
@@ -3956,31 +3998,21 @@ identify_locking_dependencies(TocEntry *te,
39563998static void
39573999reduce_dependencies (ArchiveHandle * AH ,TocEntry * te ,TocEntry * ready_list )
39584000{
3959- DumpId target = te -> dumpId ;
39604001int i ;
39614002
3962- ahlog (AH ,2 ,"reducing dependencies for %d\n" ,target );
4003+ ahlog (AH ,2 ,"reducing dependencies for %d\n" ,te -> dumpId );
39634004
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 ++ )
39704006{
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 )
39724011{
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 );
39844016}
39854017}
39864018}