|
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 | +} |