8#include "utils/maybe_ref.hpp"
31 size_t n = std::min(
name.size(),
static_cast<size_t>(
sizeof(
worker->bgw_name) - 1));
33 worker->bgw_name[n] =
'\0';
36 std::string_view name() {
return worker->bgw_name; }
39 size_t n = std::min(name.size(),
static_cast<size_t>(
sizeof(worker->bgw_type) - 1));
40 std::copy_n(name.data(), n, worker->bgw_type);
41 worker->bgw_type[n] =
'\0';
44 std::string_view type() {
return worker->bgw_type; }
47 size_t n = std::min(name.size(),
static_cast<size_t>(
sizeof(worker->bgw_library_name) - 1));
48 std::copy_n(name.data(), n, worker->bgw_library_name);
49 worker->bgw_library_name[n] =
'\0';
52 std::string_view library_name() {
return worker->bgw_library_name; }
55 size_t n = std::min(name.size(),
static_cast<size_t>(
sizeof(worker->bgw_function_name) - 1));
56 std::copy_n(name.data(), n, worker->bgw_function_name);
57 worker->bgw_function_name[n] =
'\0';
60 std::string_view function_name() {
return worker->bgw_function_name; }
63 worker->bgw_start_time = time;
67 ::BgWorkerStartTime start_time()
const {
return worker->bgw_start_time; }
70 worker->bgw_restart_time = time;
74 int restart_time()
const {
return worker->bgw_restart_time; }
77 worker->bgw_flags = flags;
81 int flags()
const {
return worker->bgw_flags; }
84 worker->bgw_main_arg = datum;
88 datum main_arg()
const {
return datum(worker->bgw_main_arg); }
91 size_t n = std::min(name.size(),
static_cast<size_t>(
sizeof(worker->bgw_extra) - 1));
92 std::copy_n(name.data(), n, worker->bgw_extra);
93 worker->bgw_extra[n] =
'\0';
96 std::string_view extra() {
return worker->bgw_extra; }
99 worker->bgw_notify_pid = pid;
103 pid_t notify_pid()
const {
return worker->bgw_notify_pid; }
105 operator BackgroundWorker &() {
return worker; }
106 operator BackgroundWorker *() {
return worker.operator->(); }
109 const char *what()
const noexcept override {
return "Background worker stopped"; }
113 const char *what()
const noexcept override {
114 return "Background worker hasn't been started yet";
119 const char *what()
const noexcept override {
return "postmaster died"; }
123 handle() : handle_(
nullptr) {}
126 ::BackgroundWorkerHandle *operator->() {
return handle_; }
128 bool has_value()
const {
return handle_ !=
nullptr; }
129 ::BackgroundWorkerHandle *
value() {
return handle_; }
131 pid_t wait_for_startup() {
137 throw std::logic_error(
"Attempting to wait for a background worker with no handle");
140 void wait_for_shutdown() {
145 throw std::logic_error(
"Attempting to wait for a background worker with no handle");
153 throw std::logic_error(
"Attempting to terminate a background worker with no handle");
165 case BGWH_NOT_YET_STARTED:
167 case BGWH_POSTMASTER_DIED:
171 throw std::logic_error(
"Attempting to get a PID of a background worker with no handle");
174 const char *worker_type() {
return ffi_guard{::GetBackgroundWorkerTypeByPid}(get_pid()); }
177 ::BackgroundWorkerHandle *handle_;
180 handle start(
bool dynamic =
true) {
182 if (::IsUnderPostmaster || !::IsPostmasterEnvironment) {
183 throw std::runtime_error(
184 "static background worker can only be start in the postmaster process");
186 ffi_guard{::RegisterBackgroundWorker}(
operator BackgroundWorker *());
189 ::BackgroundWorkerHandle *handle;
190 ffi_guard{::RegisterDynamicBackgroundWorker}(
operator BackgroundWorker *(), &handle);
195 utils::maybe_ref<::BackgroundWorker> worker = {};
199 virtual int flag()
const {
return 0; }
204 int flag()
const override {
return BGWORKER_BYPASS_ALLOWCONN; }
207#if PG_MAJORVERSION_NUM >= 17
208struct background_worker_bypass_role_login_check
210 int flag()
const override {
return BGWORKER_BYPASS_ROLELOGINCHECK; }
215 friend std::optional<current_background_worker> get_current_background_worker();
225 throw std::logic_error(
"can't access current background worker in a different backend type");
229 void unblock_signals() {
ffi_guard{::BackgroundWorkerUnblockSignals}(); }
231 void block_signals() { ffi_guard{::BackgroundWorkerBlockSignals}(); }
243 template <
typename... Flags>
244 void connect(std::string dbname, std::optional<std::string> user = std::nullopt, Flags... flags)
246 std::conjunction_v<std::is_base_of<background_worker_database_conection_flag, Flags>...>)
248 ffi_guard{::BackgroundWorkerInitializeConnection}(
249 dbname.c_str(), user.has_value() ? user.value().c_str() :
nullptr,
250 (flags.flag() | ... | 0));
263 template <
typename... Flags>
264 void connect(
oid db, std::optional<oid> user = std::nullopt, Flags... flags)
requires(
265 std::conjunction_v<std::is_base_of<background_worker_database_conection_flag, Flags>...>)
267 ffi_guard{::BackgroundWorkerInitializeConnectionByOid}(
268 db, user.has_value() ? user.value() :
oid(InvalidOid), (flags.flag() | ... | 0));
static backend_type::type type()
get current backend type
Definition: backend.hpp:49
Background worker construction and operations.
Definition: bgw.hpp:14
background_worker(::BackgroundWorker &worker)
Definition: bgw.hpp:28
background_worker()
Initialize background worker specification.
Definition: bgw.hpp:22
current_background_worker()
gets current background worker's entry
Definition: bgw.hpp:223
void connect(oid db, std::optional< oid > user=std::nullopt, Flags... flags)
Connect to the database using db oid and, optionally, user oid.
Definition: bgw.hpp:264
void connect(std::string dbname, std::optional< std::string > user=std::nullopt, Flags... flags)
Connect to the database using db name and, optionally, username.
Definition: bgw.hpp:244
Single-threaded Postgres workload worker.
Definition: threading.hpp:34