@ -91,6 +91,16 @@ typedef struct RelMapFile
int32 pad ; /* to make the struct size be 512 exactly */
int32 pad ; /* to make the struct size be 512 exactly */
} RelMapFile ;
} RelMapFile ;
/*
* State for serializing local and shared relmappings for parallel workers
* ( active states only ) . See notes on active_ * and pending_ * updates state .
*/
typedef struct SerializedActiveRelMaps
{
RelMapFile active_shared_updates ;
RelMapFile active_local_updates ;
} SerializedActiveRelMaps ;
/*
/*
* The currently known contents of the shared map file and our database ' s
* The currently known contents of the shared map file and our database ' s
* local map file are stored here . These can be reloaded from disk
* local map file are stored here . These can be reloaded from disk
@ -111,6 +121,9 @@ static RelMapFile local_map;
* they will become active at the next CommandCounterIncrement . This setup
* they will become active at the next CommandCounterIncrement . This setup
* lets map updates act similarly to updates of pg_class rows , ie , they
* lets map updates act similarly to updates of pg_class rows , ie , they
* become visible only at the next CommandCounterIncrement boundary .
* become visible only at the next CommandCounterIncrement boundary .
*
* Active shared and active local updates are serialized by the parallel
* infrastructure , and deserialized within parallel workers .
*/
*/
static RelMapFile active_shared_updates ;
static RelMapFile active_shared_updates ;
static RelMapFile active_local_updates ;
static RelMapFile active_local_updates ;
@ -263,13 +276,16 @@ RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared,
else
else
{
{
/*
/*
* We don ' t currently support map changes within subtransactions . This
* We don ' t currently support map changes within subtransactions , or
* could be done with more bookkeeping infrastructure , but it doesn ' t
* when in parallel mode . This could be done with more bookkeeping
* presently seem worth it .
* infrastructure , but it doesn ' t presently seem worth it .
*/
*/
if ( GetCurrentTransactionNestLevel ( ) > 1 )
if ( GetCurrentTransactionNestLevel ( ) > 1 )
elog ( ERROR , " cannot change relation mapping within subtransaction " ) ;
elog ( ERROR , " cannot change relation mapping within subtransaction " ) ;
if ( IsInParallelMode ( ) )
elog ( ERROR , " cannot change relation mapping in parallel mode " ) ;
if ( immediate )
if ( immediate )
{
{
/* Make it active, but only locally */
/* Make it active, but only locally */
@ -452,11 +468,14 @@ AtCCI_RelationMap(void)
*
*
* During abort , we just have to throw away any pending map changes .
* During abort , we just have to throw away any pending map changes .
* Normal post - abort cleanup will take care of fixing relcache entries .
* Normal post - abort cleanup will take care of fixing relcache entries .
* Parallel worker commit / abort is handled by resetting active mappings
* that may have been received from the leader process . ( There should be
* no pending updates in parallel workers . )
*/
*/
void
void
AtEOXact_RelationMap ( bool isCommit )
AtEOXact_RelationMap ( bool isCommit , bool isParallelWorker )
{
{
if ( isCommit )
if ( isCommit & & ! isParallelWorker )
{
{
/*
/*
* We should not get here with any " pending " updates . ( We could
* We should not get here with any " pending " updates . ( We could
@ -482,7 +501,10 @@ AtEOXact_RelationMap(bool isCommit)
}
}
else
else
{
{
/* Abort --- drop all local and pending updates */
/* Abort or parallel worker --- drop all local and pending updates */
Assert ( ! isParallelWorker | | pending_shared_updates . num_mappings = = 0 ) ;
Assert ( ! isParallelWorker | | pending_local_updates . num_mappings = = 0 ) ;
active_shared_updates . num_mappings = 0 ;
active_shared_updates . num_mappings = 0 ;
active_local_updates . num_mappings = 0 ;
active_local_updates . num_mappings = 0 ;
pending_shared_updates . num_mappings = 0 ;
pending_shared_updates . num_mappings = 0 ;
@ -614,6 +636,56 @@ RelationMapInitializePhase3(void)
load_relmap_file ( false ) ;
load_relmap_file ( false ) ;
}
}
/*
* EstimateRelationMapSpace
*
* Estimate space needed to pass active shared and local relmaps to parallel
* workers .
*/
Size
EstimateRelationMapSpace ( void )
{
return sizeof ( SerializedActiveRelMaps ) ;
}
/*
* SerializeRelationMap
*
* Serialize active shared and local relmap state for parallel workers .
*/
void
SerializeRelationMap ( Size maxSize , char * startAddress )
{
SerializedActiveRelMaps * relmaps ;
Assert ( maxSize > = EstimateRelationMapSpace ( ) ) ;
relmaps = ( SerializedActiveRelMaps * ) startAddress ;
relmaps - > active_shared_updates = active_shared_updates ;
relmaps - > active_local_updates = active_local_updates ;
}
/*
* RestoreRelationMap
*
* Restore active shared and local relmap state within a parallel worker .
*/
void
RestoreRelationMap ( char * startAddress )
{
SerializedActiveRelMaps * relmaps ;
if ( active_shared_updates . num_mappings ! = 0 | |
active_local_updates . num_mappings ! = 0 | |
pending_shared_updates . num_mappings ! = 0 | |
pending_local_updates . num_mappings ! = 0 )
elog ( ERROR , " parallel worker has existing mappings " ) ;
relmaps = ( SerializedActiveRelMaps * ) startAddress ;
active_shared_updates = relmaps - > active_shared_updates ;
active_local_updates = relmaps - > active_local_updates ;
}
/*
/*
* load_relmap_file - - load data from the shared or local map file
* load_relmap_file - - load data from the shared or local map file
*
*