24
24
#include "storage/shm_toc.h"
25
25
#include "utils/datetime.h"
26
26
#include "utils/guc.h"
27
+ #include "utils/guc_tables.h"
27
28
#include "utils/wait.h"
28
29
29
30
PG_MODULE_MAGIC ;
@@ -121,6 +122,80 @@ shmem_bool_guc_check_hook(bool *newval, void **extra, GucSource source)
121
122
return true;
122
123
}
123
124
125
+ /*
126
+ * This union allows us to mix the numerous different types of structs
127
+ * that we are organizing.
128
+ */
129
+ typedef union
130
+ {
131
+ struct config_generic generic ;
132
+ struct config_bool _bool ;
133
+ struct config_real real ;
134
+ struct config_int integer ;
135
+ struct config_string string ;
136
+ struct config_enum _enum ;
137
+ }mixedStruct ;
138
+
139
+ static void
140
+ set_history_gucs ()
141
+ {
142
+ struct config_generic * * guc_vars ;
143
+ int numOpts ,
144
+ i ;
145
+ bool history_size_found = false,
146
+ history_period_found = false,
147
+ history_skip_latch_found = false;
148
+
149
+ /* Initialize the guc_variables[] array */
150
+ build_guc_variables ();
151
+
152
+ guc_vars = get_guc_variables ();
153
+ numOpts = GetNumConfigOptions ();
154
+
155
+ for (i = 0 ;i < numOpts ;i ++ )
156
+ {
157
+ mixedStruct * var = (mixedStruct * )guc_vars [i ];
158
+ const char * name = var -> generic .name ;
159
+
160
+ if (!strcmp (name ,"pg_stat_wait.history_size" ))
161
+ {
162
+ history_size_found = true;
163
+ var -> integer .variable = & collector_hdr -> historySize ;
164
+ }
165
+ else if (!strcmp (name ,"pg_stat_wait.history_period" ))
166
+ {
167
+ history_period_found = true;
168
+ var -> integer .variable = & collector_hdr -> historyPeriod ;
169
+ }
170
+ else if (!strcmp (name ,"pg_stat_wait.history_skip_latch" ))
171
+ {
172
+ history_skip_latch_found = true;
173
+ var -> _bool .variable = & collector_hdr -> historySkipLatch ;
174
+ }
175
+ }
176
+
177
+ if (!history_size_found )
178
+ DefineCustomIntVariable ("pg_stat_wait.history_size" ,
179
+ "Sets size of waits history." ,NULL ,
180
+ & collector_hdr -> historySize ,5000 ,100 ,INT_MAX ,
181
+ PGC_SUSET ,GUC_CUSTOM_PLACEHOLDER ,
182
+ shmem_int_guc_check_hook ,NULL ,NULL );
183
+
184
+ if (!history_period_found )
185
+ DefineCustomIntVariable ("pg_stat_wait.history_period" ,
186
+ "Sets period of waits history sampling." ,NULL ,
187
+ & collector_hdr -> historyPeriod ,10 ,1 ,INT_MAX ,
188
+ PGC_SUSET ,GUC_CUSTOM_PLACEHOLDER ,
189
+ shmem_int_guc_check_hook ,NULL ,NULL );
190
+
191
+ if (!history_skip_latch_found )
192
+ DefineCustomBoolVariable ("pg_stat_wait.history_skip_latch" ,
193
+ "Skip latch events in waits history" ,NULL ,
194
+ & collector_hdr -> historySkipLatch , false,
195
+ PGC_SUSET ,GUC_CUSTOM_PLACEHOLDER ,
196
+ shmem_bool_guc_check_hook ,NULL ,NULL );
197
+ }
198
+
124
199
/*
125
200
* Distribute shared memory.
126
201
*/
@@ -155,6 +230,7 @@ pgsw_shmem_startup(void)
155
230
shm_toc_insert (toc ,3 ,collector_hdr );
156
231
collector_mq = shm_toc_allocate (toc ,COLLECTOR_QUEUE_SIZE );
157
232
shm_toc_insert (toc ,4 ,collector_mq );
233
+ set_history_gucs ();
158
234
}
159
235
}
160
236
else
@@ -172,24 +248,6 @@ pgsw_shmem_startup(void)
172
248
}
173
249
}
174
250
175
- if (waitsHistoryOn )
176
- {
177
- DefineCustomIntVariable ("pg_stat_wait.history_size" ,
178
- "Sets size of waits history." ,NULL ,
179
- & collector_hdr -> historySize ,5000 ,100 ,INT_MAX ,
180
- PGC_SUSET ,0 ,shmem_int_guc_check_hook ,NULL ,NULL );
181
-
182
- DefineCustomIntVariable ("pg_stat_wait.history_period" ,
183
- "Sets period of waits history sampling." ,NULL ,
184
- & collector_hdr -> historyPeriod ,10 ,1 ,INT_MAX ,
185
- PGC_SUSET ,0 ,shmem_int_guc_check_hook ,NULL ,NULL );
186
-
187
- DefineCustomBoolVariable ("pg_stat_wait.history_skip_latch" ,
188
- "Skip latch events in waits history" ,NULL ,
189
- & collector_hdr -> historySkipLatch , false,
190
- PGC_SUSET ,0 ,shmem_bool_guc_check_hook ,NULL ,NULL );
191
- }
192
-
193
251
shmem_initialized = true;
194
252
195
253
if (prev_shmem_startup_hook )
@@ -523,6 +581,8 @@ pg_stat_wait_get_current(PG_FUNCTION_ARGS)
523
581
FuncCallContext * funcctx ;
524
582
WaitCurrentContext * params ;
525
583
584
+ check_shmem ();
585
+
526
586
if (SRF_IS_FIRSTCALL ())
527
587
{
528
588
MemoryContext oldcontext ;
@@ -641,6 +701,8 @@ pg_stat_wait_get_profile(PG_FUNCTION_ARGS)
641
701
WaitProfileContext * params ;
642
702
FuncCallContext * funcctx ;
643
703
704
+ check_shmem ();
705
+
644
706
if (SRF_IS_FIRSTCALL ())
645
707
{
646
708
MemoryContext oldcontext ;
@@ -755,6 +817,8 @@ pg_stat_wait_reset_profile(PG_FUNCTION_ARGS)
755
817
{
756
818
int i ;
757
819
820
+ check_shmem ();
821
+
758
822
for (i = 0 ;i < maxProcs * WAIT_EVENTS_COUNT ;i ++ )
759
823
{
760
824
profile [i ].count = 0 ;
@@ -835,6 +899,10 @@ pg_stat_wait_get_history(PG_FUNCTION_ARGS)
835
899
mq = shm_mq_create (collector_mq ,COLLECTOR_QUEUE_SIZE );
836
900
collector_hdr -> request = HISTORY_REQUEST ;
837
901
902
+ if (!collector_hdr -> latch )
903
+ ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ),
904
+ errmsg ("pg_stat_wait collector wasn't started" )));
905
+
838
906
SetLatch (collector_hdr -> latch );
839
907
840
908
shm_mq_set_receiver (mq ,MyProc );
@@ -908,6 +976,8 @@ pg_start_trace(PG_FUNCTION_ARGS)
908
976
TraceInfo * traceItem ;
909
977
char * filename = PG_GETARG_CSTRING (1 );
910
978
979
+ check_shmem ();
980
+
911
981
if (strlen (filename )> WAIT_TRACE_FN_LEN )
912
982
ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ),
913
983
errmsg ("length of filename limited to %d" ,WAIT_TRACE_FN_LEN )));
@@ -949,6 +1019,8 @@ pg_is_in_trace(PG_FUNCTION_ARGS)
949
1019
int procno ;
950
1020
TraceInfo * traceItem ;
951
1021
1022
+ check_shmem ();
1023
+
952
1024
if (PG_ARGISNULL (0 ))
953
1025
{
954
1026
procno = MyProc -> pgprocno ;
@@ -973,6 +1045,8 @@ pg_stop_trace(PG_FUNCTION_ARGS)
973
1045
int procno ;
974
1046
TraceInfo * traceItem ;
975
1047
1048
+ check_shmem ();
1049
+
976
1050
if (PG_ARGISNULL (0 ))
977
1051
{
978
1052
procno = MyProc -> pgprocno ;
@@ -1008,6 +1082,8 @@ pg_stat_wait_start_wait(PG_FUNCTION_ARGS)
1008
1082
int p4 = PG_GETARG_INT32 (5 );
1009
1083
int p5 = PG_GETARG_INT32 (6 );
1010
1084
1085
+ check_shmem ();
1086
+
1011
1087
WAIT_START (classId ,eventId ,p1 ,p2 ,p3 ,p4 ,p5 );
1012
1088
PG_RETURN_VOID ();
1013
1089
}
@@ -1017,6 +1093,8 @@ PG_FUNCTION_INFO_V1(pg_stat_wait_stop_wait);
1017
1093
Datum
1018
1094
pg_stat_wait_stop_wait (PG_FUNCTION_ARGS )
1019
1095
{
1096
+ check_shmem ();
1097
+
1020
1098
WAIT_STOP ();
1021
1099
PG_RETURN_VOID ();
1022
1100
}