|
15 | 15 | #include<unistd.h>
|
16 | 16 |
|
17 | 17 | #include"libpq/pqsignal.h"
|
| 18 | +#include"access/parallel.h" |
18 | 19 | #include"miscadmin.h"
|
19 | 20 | #include"pgstat.h"
|
20 | 21 | #include"port/atomics.h"
|
21 | 22 | #include"postmaster/bgworker_internals.h"
|
22 | 23 | #include"postmaster/postmaster.h"
|
23 | 24 | #include"replication/logicallauncher.h"
|
| 25 | +#include"replication/logicalworker.h" |
24 | 26 | #include"storage/dsm.h"
|
25 | 27 | #include"storage/ipc.h"
|
26 | 28 | #include"storage/latch.h"
|
@@ -109,14 +111,26 @@ struct BackgroundWorkerHandle
|
109 | 111 | staticBackgroundWorkerArray*BackgroundWorkerData;
|
110 | 112 |
|
111 | 113 | /*
|
112 |
| - * List of workers that are allowed to be started outside of |
113 |
| - * shared_preload_libraries. |
| 114 | + * List of internal background workers. These are used for mapping the |
| 115 | + * function name to actual function when building with EXEC_BACKEND and also |
| 116 | + * to allow these to be loaded outside of shared_preload_libraries. |
114 | 117 | */
|
115 |
| -staticconstbgworker_main_typeInternalBGWorkers[]= { |
116 |
| -ApplyLauncherMain, |
117 |
| -NULL |
| 118 | +typedefstructInternalBGWorkerMain |
| 119 | +{ |
| 120 | +char*bgw_function_name; |
| 121 | +bgworker_main_typebgw_main; |
| 122 | +}InternalBGWorkerMain; |
| 123 | + |
| 124 | +staticconstInternalBGWorkerMainInternalBGWorkers[]= { |
| 125 | +{"ParallelWorkerMain",ParallelWorkerMain}, |
| 126 | +{"ApplyLauncherMain",ApplyLauncherMain}, |
| 127 | +{"ApplyWorkerMain",ApplyWorkerMain}, |
| 128 | +/* Dummy entry marking end of the array. */ |
| 129 | +{NULL,NULL} |
118 | 130 | };
|
119 | 131 |
|
| 132 | +staticbgworker_main_typeGetInternalBgWorkerMain(BackgroundWorker*worker); |
| 133 | + |
120 | 134 | /*
|
121 | 135 | * Calculate shared memory needed.
|
122 | 136 | */
|
@@ -341,7 +355,6 @@ BackgroundWorkerStateChange(void)
|
341 | 355 | rw->rw_worker.bgw_flags=slot->worker.bgw_flags;
|
342 | 356 | rw->rw_worker.bgw_start_time=slot->worker.bgw_start_time;
|
343 | 357 | rw->rw_worker.bgw_restart_time=slot->worker.bgw_restart_time;
|
344 |
| -rw->rw_worker.bgw_main=slot->worker.bgw_main; |
345 | 358 | rw->rw_worker.bgw_main_arg=slot->worker.bgw_main_arg;
|
346 | 359 | memcpy(rw->rw_worker.bgw_extra,slot->worker.bgw_extra,BGW_EXTRALEN);
|
347 | 360 |
|
@@ -763,17 +776,14 @@ StartBackgroundWorker(void)
|
763 | 776 | }
|
764 | 777 |
|
765 | 778 | /*
|
766 |
| - * If bgw_main is set, we use that value as the initial entrypoint. |
767 |
| - * However, if the library containing the entrypoint wasn't loaded at |
768 |
| - * postmaster startup time, passing it as a direct function pointer is not |
769 |
| - * possible. To work around that, we allow callers for whom a function |
770 |
| - * pointer is not available to pass a library name (which will be loaded, |
771 |
| - * if necessary) and a function name (which will be looked up in the named |
772 |
| - * library). |
| 779 | + * For internal workers set the entry point to known function address. |
| 780 | + * Otherwise use the entry point specified by library name (which will |
| 781 | + * be loaded, if necessary) and a function name (which will be looked up |
| 782 | + * in the named library). |
773 | 783 | */
|
774 |
| -if (worker->bgw_main!=NULL) |
775 |
| -entrypt=worker->bgw_main; |
776 |
| -else |
| 784 | +entrypt=GetInternalBgWorkerMain(worker); |
| 785 | + |
| 786 | +if (entrypt==NULL) |
777 | 787 | entrypt= (bgworker_main_type)
|
778 | 788 | load_external_function(worker->bgw_library_name,
|
779 | 789 | worker->bgw_function_name,
|
@@ -806,23 +816,13 @@ RegisterBackgroundWorker(BackgroundWorker *worker)
|
806 | 816 | {
|
807 | 817 | RegisteredBgWorker*rw;
|
808 | 818 | staticintnumworkers=0;
|
809 |
| -boolinternal= false; |
810 |
| -inti; |
811 | 819 |
|
812 | 820 | if (!IsUnderPostmaster)
|
813 | 821 | ereport(DEBUG1,
|
814 | 822 | (errmsg("registering background worker \"%s\"",worker->bgw_name)));
|
815 | 823 |
|
816 |
| -for (i=0;InternalBGWorkers[i];i++) |
817 |
| -{ |
818 |
| -if (worker->bgw_main==InternalBGWorkers[i]) |
819 |
| -{ |
820 |
| -internal= true; |
821 |
| -break; |
822 |
| -} |
823 |
| -} |
824 |
| - |
825 |
| -if (!process_shared_preload_libraries_in_progress&& !internal) |
| 824 | +if (!process_shared_preload_libraries_in_progress&& |
| 825 | +GetInternalBgWorkerMain(worker)==NULL) |
826 | 826 | {
|
827 | 827 | if (!IsUnderPostmaster)
|
828 | 828 | ereport(LOG,
|
@@ -1152,3 +1152,28 @@ TerminateBackgroundWorker(BackgroundWorkerHandle *handle)
|
1152 | 1152 | if (signal_postmaster)
|
1153 | 1153 | SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
|
1154 | 1154 | }
|
| 1155 | + |
| 1156 | +/* |
| 1157 | + * Search the known internal worker array and return its main function |
| 1158 | + * pointer if found. |
| 1159 | + * |
| 1160 | + * Returns NULL if not known internal worker. |
| 1161 | + */ |
| 1162 | +staticbgworker_main_type |
| 1163 | +GetInternalBgWorkerMain(BackgroundWorker*worker) |
| 1164 | +{ |
| 1165 | +inti; |
| 1166 | + |
| 1167 | +/* Internal workers always have to use postgres as library name. */ |
| 1168 | +if (strncmp(worker->bgw_library_name,"postgres",BGW_MAXLEN)!=0) |
| 1169 | +returnNULL; |
| 1170 | + |
| 1171 | +for (i=0;InternalBGWorkers[i].bgw_function_name;i++) |
| 1172 | +{ |
| 1173 | +if (strncmp(InternalBGWorkers[i].bgw_function_name, |
| 1174 | +worker->bgw_function_name,BGW_MAXLEN)==0) |
| 1175 | +returnInternalBGWorkers[i].bgw_main; |
| 1176 | +} |
| 1177 | + |
| 1178 | +returnNULL; |
| 1179 | +} |