@@ -78,7 +78,7 @@ char *SyncRepStandbyNames;
78
78
79
79
static bool announce_next_takeover = true;
80
80
81
- SyncRepConfigData * SyncRepConfig ;
81
+ static SyncRepConfigData * SyncRepConfig = NULL ;
82
82
static int SyncRepWaitMode = SYNC_REP_NO_WAIT ;
83
83
84
84
static void SyncRepQueueInsert (int mode );
@@ -361,11 +361,6 @@ SyncRepInitConfig(void)
361
361
{
362
362
int priority ;
363
363
364
- /* Update the config data of synchronous replication */
365
- SyncRepFreeConfig (SyncRepConfig );
366
- SyncRepConfig = NULL ;
367
- SyncRepUpdateConfig ();
368
-
369
364
/*
370
365
* Determine if we are a potential sync standby and remember the result
371
366
* for handling replies from standby.
@@ -509,7 +504,9 @@ SyncRepGetOldestSyncRecPtr(XLogRecPtr *writePtr, XLogRecPtr *flushPtr,
509
504
* Quick exit if we are not managing a sync standby or there are not
510
505
* enough synchronous standbys.
511
506
*/
512
- if (!(* am_sync ) || list_length (sync_standbys ) < SyncRepConfig -> num_sync )
507
+ if (!(* am_sync ) ||
508
+ SyncRepConfig == NULL ||
509
+ list_length (sync_standbys ) < SyncRepConfig -> num_sync )
513
510
{
514
511
list_free (sync_standbys );
515
512
return false;
@@ -568,14 +565,15 @@ SyncRepGetSyncStandbys(bool *am_sync)
568
565
volatile WalSnd * walsnd ; /* Use volatile pointer to prevent
569
566
* code rearrangement */
570
567
568
+ /* Set default result */
569
+ if (am_sync != NULL )
570
+ * am_sync = false;
571
+
571
572
/* Quick exit if sync replication is not requested */
572
573
if (SyncRepConfig == NULL )
573
574
return NIL ;
574
575
575
- if (am_sync != NULL )
576
- * am_sync = false;
577
-
578
- lowest_priority = list_length (SyncRepConfig -> members );
576
+ lowest_priority = SyncRepConfig -> nmembers ;
579
577
next_highest_priority = lowest_priority + 1 ;
580
578
581
579
/*
@@ -730,9 +728,8 @@ SyncRepGetSyncStandbys(bool *am_sync)
730
728
static int
731
729
SyncRepGetStandbyPriority (void )
732
730
{
733
- List * members ;
734
- ListCell * l ;
735
- int priority = 0 ;
731
+ const char * standby_name ;
732
+ int priority ;
736
733
bool found = false;
737
734
738
735
/*
@@ -742,22 +739,19 @@ SyncRepGetStandbyPriority(void)
742
739
if (am_cascading_walsender )
743
740
return 0 ;
744
741
745
- if (!SyncStandbysDefined ())
742
+ if (!SyncStandbysDefined () || SyncRepConfig == NULL )
746
743
return 0 ;
747
744
748
- members = SyncRepConfig -> members ;
749
- foreach ( l , members )
745
+ standby_name = SyncRepConfig -> member_names ;
746
+ for ( priority = 1 ; priority <= SyncRepConfig -> nmembers ; priority ++ )
750
747
{
751
- char * standby_name = (char * ) lfirst (l );
752
-
753
- priority ++ ;
754
-
755
748
if (pg_strcasecmp (standby_name , application_name ) == 0 ||
756
- pg_strcasecmp (standby_name , "*" ) == 0 )
749
+ strcmp (standby_name , "*" ) == 0 )
757
750
{
758
751
found = true;
759
752
break ;
760
753
}
754
+ standby_name += strlen (standby_name ) + 1 ;
761
755
}
762
756
763
757
return (found ? priority : 0 );
@@ -867,50 +861,6 @@ SyncRepUpdateSyncStandbysDefined(void)
867
861
}
868
862
}
869
863
870
- /*
871
- * Parse synchronous_standby_names and update the config data
872
- * of synchronous standbys.
873
- */
874
- void
875
- SyncRepUpdateConfig (void )
876
- {
877
- int parse_rc ;
878
-
879
- if (!SyncStandbysDefined ())
880
- return ;
881
-
882
- /*
883
- * check_synchronous_standby_names() verifies the setting value of
884
- * synchronous_standby_names before this function is called. So
885
- * syncrep_yyparse() must not cause an error here.
886
- */
887
- syncrep_scanner_init (SyncRepStandbyNames );
888
- parse_rc = syncrep_yyparse ();
889
- syncrep_scanner_finish ();
890
-
891
- if (parse_rc != 0 )
892
- ereport (ERROR ,
893
- (errcode (ERRCODE_SYNTAX_ERROR ),
894
- errmsg_internal ("synchronous_standby_names parser returned %d" ,
895
- parse_rc )));
896
-
897
- SyncRepConfig = syncrep_parse_result ;
898
- syncrep_parse_result = NULL ;
899
- }
900
-
901
- /*
902
- * Free a previously-allocated config data of synchronous replication.
903
- */
904
- void
905
- SyncRepFreeConfig (SyncRepConfigData * config )
906
- {
907
- if (!config )
908
- return ;
909
-
910
- list_free_deep (config -> members );
911
- pfree (config );
912
- }
913
-
914
864
#ifdef USE_ASSERT_CHECKING
915
865
static bool
916
866
SyncRepQueueIsOrderedByLSN (int mode )
@@ -955,78 +905,104 @@ SyncRepQueueIsOrderedByLSN(int mode)
955
905
bool
956
906
check_synchronous_standby_names (char * * newval , void * * extra , GucSource source )
957
907
{
958
- int parse_rc ;
959
-
960
908
if (* newval != NULL && (* newval )[0 ] != '\0' )
961
909
{
910
+ int parse_rc ;
911
+ SyncRepConfigData * pconf ;
912
+
913
+ /* Reset communication variables to ensure a fresh start */
914
+ syncrep_parse_result = NULL ;
915
+ syncrep_parse_error_msg = NULL ;
916
+
917
+ /* Parse the synchronous_standby_names string */
962
918
syncrep_scanner_init (* newval );
963
919
parse_rc = syncrep_yyparse ();
964
920
syncrep_scanner_finish ();
965
921
966
- if (parse_rc != 0 )
922
+ if (parse_rc != 0 || syncrep_parse_result == NULL )
967
923
{
968
924
GUC_check_errcode (ERRCODE_SYNTAX_ERROR );
969
- GUC_check_errdetail ("synchronous_standby_names parser returned %d" ,
970
- parse_rc );
925
+ if (syncrep_parse_error_msg )
926
+ GUC_check_errdetail ("%s" , syncrep_parse_error_msg );
927
+ else
928
+ GUC_check_errdetail ("synchronous_standby_names parser failed" );
971
929
return false;
972
930
}
973
931
974
932
/*
975
933
* Warn if num_sync exceeds the number of names of potential sync
976
- * standbys. This setting doesn't make sense in most cases because
977
- * it implies that enough number of sync standbys will not appear,
978
- * which makes transaction commits wait for sync replication
979
- * infinitely.
934
+ * standbys. This setting doesn't make sense in most cases because it
935
+ * implies that enough number of sync standbys will not appear, which
936
+ * makes transaction commits wait for sync replication infinitely.
980
937
*
981
938
* If there are more than one standbys having the same name and
982
939
* priority, we can see enough sync standbys to complete transaction
983
- * commits. However it's not recommended to run multiple standbys
984
- * with the same priority because we cannot gain full control of
985
- * the selection of sync standbys from them.
940
+ * commits. However it's not recommended to run multiple standbys with
941
+ * the same priority because we cannot gain full control of the
942
+ * selection of sync standbys from them.
986
943
*
987
944
* OTOH, that setting is OK if we understand the above problem
988
- * regarding the selection of sync standbys and intentionally
989
- * specify * to match all the standbys.
945
+ * regarding the selection of sync standbys and intentionally specify *
946
+ * to match all the standbys.
990
947
*/
991
- if (syncrep_parse_result -> num_sync >
992
- list_length (syncrep_parse_result -> members ))
948
+ if (syncrep_parse_result -> num_sync > syncrep_parse_result -> nmembers )
993
949
{
994
- ListCell * l ;
995
- bool has_asterisk = false;
950
+ const char * standby_name ;
951
+ int i ;
952
+ bool has_asterisk = false;
996
953
997
- foreach (l , syncrep_parse_result -> members )
954
+ standby_name = syncrep_parse_result -> member_names ;
955
+ for (i = 1 ; i <= syncrep_parse_result -> nmembers ; i ++ )
998
956
{
999
- char * standby_name = (char * ) lfirst (l );
1000
-
1001
- if (pg_strcasecmp (standby_name , "*" ) == 0 )
957
+ if (strcmp (standby_name , "*" ) == 0 )
1002
958
{
1003
959
has_asterisk = true;
1004
960
break ;
1005
961
}
962
+ standby_name += strlen (standby_name ) + 1 ;
1006
963
}
1007
964
1008
965
/*
1009
- * Only the postmaster warns this inappropriate setting
1010
- * to avoid cluttering the log.
966
+ * Only the postmaster warns about this inappropriate setting to
967
+ * avoid cluttering the log.
1011
968
*/
1012
969
if (!has_asterisk && !IsUnderPostmaster )
1013
970
ereport (WARNING ,
1014
- (errmsg ("The configured number of synchronous standbys (%d) exceeds the number of names of potential synchronous ones (%d)" ,
1015
- syncrep_parse_result -> num_sync , list_length (syncrep_parse_result -> members )),
971
+ (errmsg ("configured number of synchronous standbys (%d) exceeds the number of names of potential synchronous ones (%d)" ,
972
+ syncrep_parse_result -> num_sync ,
973
+ syncrep_parse_result -> nmembers ),
1016
974
errhint ("Specify more names of potential synchronous standbys in synchronous_standby_names." )));
1017
975
}
1018
976
977
+ /* GUC extra value must be malloc'd, not palloc'd */
978
+ pconf = (SyncRepConfigData * )
979
+ malloc (syncrep_parse_result -> config_size );
980
+ if (pconf == NULL )
981
+ return false;
982
+ memcpy (pconf , syncrep_parse_result , syncrep_parse_result -> config_size );
983
+
984
+ * extra = (void * ) pconf ;
985
+
1019
986
/*
1020
- * syncrep_yyparse sets the global syncrep_parse_result as side effect.
1021
- * But this function is required to just check, so frees it
1022
- * after parsing the parameter.
987
+ * We need not explicitly clean up syncrep_parse_result. It, and any
988
+ * other cruft generated during parsing, will be freed when the
989
+ * current memory context is deleted. (This code is generally run in
990
+ * a short-lived context used for config file processing, so that will
991
+ * not be very long.)
1023
992
*/
1024
- SyncRepFreeConfig (syncrep_parse_result );
1025
993
}
994
+ else
995
+ * extra = NULL ;
1026
996
1027
997
return true;
1028
998
}
1029
999
1000
+ void
1001
+ assign_synchronous_standby_names (const char * newval , void * extra )
1002
+ {
1003
+ SyncRepConfig = (SyncRepConfigData * ) extra ;
1004
+ }
1005
+
1030
1006
void
1031
1007
assign_synchronous_commit (int newval , void * extra )
1032
1008
{
0 commit comments