1
+ /*
2
+ * pg_stat_wait.c
3
+ *Track information about wait events.
4
+ *
5
+ * Copyright (c) 2015-2016, Postgres Professional
6
+ *
7
+ * IDENTIFICATION
8
+ * contrib/pg_stat_wait/pg_stat_waits.c
9
+ */
1
10
#include "postgres.h"
2
11
#include "fmgr.h"
3
12
#include "funcapi.h"
@@ -26,11 +35,14 @@ boolwaitsHistoryOn;
26
35
int historySize ;
27
36
int historyPeriod ;
28
37
bool historySkipLatch ;
38
+
39
+ /* Shared memory variables */
29
40
shm_toc * toc = NULL ;
30
41
CollectorShmqHeader * collector_hdr = NULL ;
31
42
shm_mq * collector_mq = NULL ;
32
43
CurrentWaitEventWrap * cur_wait_events = NULL ;
33
44
ProfileItem * profile = NULL ;
45
+ TraceInfo * trace_info = NULL ;
34
46
35
47
static int maxProcs ;
36
48
@@ -57,7 +69,8 @@ pgsw_shmem_size(void)
57
69
58
70
shm_toc_estimate_chunk (& e ,sizeof (CurrentWaitEventWrap )* maxProcs );
59
71
shm_toc_estimate_chunk (& e ,sizeof (ProfileItem )* maxProcs * WAIT_EVENTS_COUNT );
60
- nkeys = 2 ;
72
+ shm_toc_estimate_chunk (& e ,sizeof (TraceInfo )* maxProcs );
73
+ nkeys = 3 ;
61
74
62
75
if (waitsHistoryOn )
63
76
{
@@ -72,6 +85,9 @@ pgsw_shmem_size(void)
72
85
return size ;
73
86
}
74
87
88
+ /*
89
+ * Make initial state of current wait events.
90
+ */
75
91
static void
76
92
init_current_wait_event ()
77
93
{
@@ -114,12 +130,16 @@ pgsw_shmem_startup(void)
114
130
shm_toc_insert (toc ,1 ,profile );
115
131
memset (profile ,0 ,sizeof (ProfileItem )* maxProcs * WAIT_EVENTS_COUNT );
116
132
133
+ trace_info = shm_toc_allocate (toc ,sizeof (TraceInfo )* maxProcs );
134
+ shm_toc_insert (toc ,2 ,trace_info );
135
+ memset (trace_info ,0 ,sizeof (TraceInfo )* maxProcs );
136
+
117
137
if (waitsHistoryOn )
118
138
{
119
139
collector_hdr = shm_toc_allocate (toc ,sizeof (CollectorShmqHeader ));
120
- shm_toc_insert (toc ,2 ,collector_hdr );
140
+ shm_toc_insert (toc ,3 ,collector_hdr );
121
141
collector_mq = shm_toc_allocate (toc ,COLLECTOR_QUEUE_SIZE );
122
- shm_toc_insert (toc ,3 ,collector_mq );
142
+ shm_toc_insert (toc ,4 ,collector_mq );
123
143
}
124
144
}
125
145
else
@@ -128,11 +148,12 @@ pgsw_shmem_startup(void)
128
148
129
149
cur_wait_events = shm_toc_lookup (toc ,0 );
130
150
profile = shm_toc_lookup (toc ,1 );
151
+ trace_info = shm_toc_lookup (toc ,2 );
131
152
132
153
if (waitsHistoryOn )
133
154
{
134
- collector_hdr = shm_toc_lookup (toc ,2 );
135
- collector_mq = shm_toc_lookup (toc ,3 );
155
+ collector_hdr = shm_toc_lookup (toc ,3 );
156
+ collector_mq = shm_toc_lookup (toc ,4 );
136
157
}
137
158
}
138
159
@@ -308,6 +329,9 @@ _PG_fini(void)
308
329
shmem_startup_hook = prev_shmem_startup_hook ;
309
330
}
310
331
332
+ /*
333
+ * Make a TupleDesc describing single item of waits history.
334
+ */
311
335
static TupleDesc
312
336
get_history_item_tupledesc ()
313
337
{
@@ -459,7 +483,7 @@ get_proc_pid_by_idx(int i)
459
483
}
460
484
461
485
static int
462
- find_proc_offset (int pid )
486
+ find_procno (int pid )
463
487
{
464
488
int i ,result = -1 ;
465
489
@@ -499,7 +523,7 @@ pg_stat_wait_get_profile(PG_FUNCTION_ARGS)
499
523
if (!PG_ARGISNULL (0 ))
500
524
{
501
525
params -> procPid = PG_GETARG_UINT32 (0 );
502
- params -> procIdx = find_proc_offset (params -> procPid );
526
+ params -> procIdx = find_procno (params -> procPid );
503
527
}
504
528
else
505
529
{
@@ -749,34 +773,40 @@ PG_FUNCTION_INFO_V1(pg_start_trace);
749
773
Datum
750
774
pg_start_trace (PG_FUNCTION_ARGS )
751
775
{
752
- #ifdef NOT_USED
753
- PGPROC * proc ;
776
+ int procno ;
777
+ TraceInfo * traceItem ;
754
778
char * filename = PG_GETARG_CSTRING (1 );
755
779
756
- if (strlen (filename ) >= WAIT_TRACE_FN_LEN )
780
+ if (strlen (filename )> WAIT_TRACE_FN_LEN )
757
781
ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ),
758
- errmsg ("length of filename limited to %d" ,( WAIT_TRACE_FN_LEN - 1 ) )));
782
+ errmsg ("length of filename limited to %d" ,WAIT_TRACE_FN_LEN )));
759
783
760
784
if (!is_absolute_path (filename ))
761
785
ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ),
762
786
errmsg ("path must be absolute" )));
763
787
764
- proc = NULL ;
765
788
if (PG_ARGISNULL (0 ))
766
- proc = MyProc ;
789
+ {
790
+ procno = MyProc -> pgprocno ;
791
+ }
767
792
else
768
- proc = search_proc (PG_GETARG_INT32 (0 ));
769
-
770
- if (proc != NULL )
771
793
{
772
- if (proc -> waits .traceOn )
794
+ procno = find_procno (PG_GETARG_INT32 (0 ));
795
+ if (procno < 0 )
773
796
ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ),
774
- errmsg ("trace is already working in backend" )));
775
-
776
- strcpy (proc -> waits .traceFn ,filename );
777
- proc -> waits .traceOn = true;
797
+ errmsg ("pid is not found" )));
778
798
}
779
- #endif
799
+
800
+ traceItem = & trace_info [procno ];
801
+ if (traceItem -> traceOn )
802
+ ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ),
803
+ errmsg ("trace is already working in backend" )));
804
+
805
+ strcpy (traceItem -> filename ,filename );
806
+
807
+ pg_write_barrier ();
808
+
809
+ traceItem -> traceOn = true;
780
810
781
811
PG_RETURN_VOID ();
782
812
}
@@ -785,41 +815,51 @@ PG_FUNCTION_INFO_V1(pg_is_in_trace);
785
815
Datum
786
816
pg_is_in_trace (PG_FUNCTION_ARGS )
787
817
{
788
- #ifdef NOT_USED
789
- PGPROC * proc = NULL ;
818
+ int procno ;
819
+ TraceInfo * traceItem ;
790
820
791
821
if (PG_ARGISNULL (0 ))
792
- proc = MyProc ;
822
+ {
823
+ procno = MyProc -> pgprocno ;
824
+ }
793
825
else
794
- proc = search_proc (PG_GETARG_INT32 (0 ));
826
+ {
827
+ procno = find_procno (PG_GETARG_INT32 (0 ));
828
+ if (procno < 0 )
829
+ ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ),
830
+ errmsg ("pid is not found" )));
831
+ }
795
832
796
- if (proc )
797
- PG_RETURN_BOOL (proc -> waits .traceOn );
798
- #endif
833
+ traceItem = & trace_info [procno ];
799
834
800
- PG_RETURN_BOOL (false );
835
+ PG_RETURN_BOOL (traceItem -> traceOn );
801
836
}
802
837
803
838
PG_FUNCTION_INFO_V1 (pg_stop_trace );
804
839
Datum
805
840
pg_stop_trace (PG_FUNCTION_ARGS )
806
841
{
807
- PGPROC * proc = NULL ;
842
+ int procno ;
843
+ TraceInfo * traceItem ;
844
+
808
845
if (PG_ARGISNULL (0 ))
809
- proc = MyProc ;
846
+ {
847
+ procno = MyProc -> pgprocno ;
848
+ }
810
849
else
811
- proc = search_proc (PG_GETARG_INT32 (0 ));
812
-
813
- #ifdef NOT_USED
814
- if (proc != NULL )
815
850
{
816
- if (!proc -> waits .traceOn )
851
+ procno = find_procno (PG_GETARG_INT32 (0 ));
852
+ if (procno < 0 )
817
853
ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ),
818
- errmsg ("trace is not started" )));
819
-
820
- proc -> waits .traceOn = false;
854
+ errmsg ("pid is not found" )));
821
855
}
822
- #endif
856
+
857
+ traceItem = & trace_info [procno ];
858
+ if (!traceItem -> traceOn )
859
+ ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ),
860
+ errmsg ("trace is not started" )));
861
+
862
+ traceItem -> traceOn = false;
823
863
824
864
PG_RETURN_VOID ();
825
865
}