title |
---|
Managing & Developing Extensions |
omni
is a Postgres shared library (and also an extension) that helps managing and developing Postgres easier. Think of it like an extension for extensions !
Postgres extension eco-system is growing rapidly, however the tooling/infrastructure around that has a lot of catch up to do. For eg. an extension that allocates shared memory or spins up background workers requires restarting Postgres.
- Hooks initialization
- Allocate/Deallocate shared memory
- Managing background workers
- Upgrading extensions
- Setting custom GUC
To find the latest version of omni
curl -s https://index.omnigres.com/16/Release/ubuntu-x86-64/index.json | jq .
To download and install omni
curl -s https://raw.githubusercontent.com/omnigres/omnigres/master/download-omnigres-extension.sh | bash -s install omni 0.1.2
postgres=# create extension omni;
or use omni_manifest.install()
to install it.
- Include omni header file omni_v0.h
- Declare
OMNI_MAGIC
in your extension - Create a function
dummy
- Define the callback function
_Omni_init
- Update postgresql.conf shared_preload_libraies config to include
omni
Declare a hook variable which is of type omni_hook
and register that with the handle (of type omni_handle
) in the callback function _Omni_init
.
Example:
void planner_hook_fn(omni_hook_handle *handle, Query *parse, const char *query_string,
int cursorOptions, ParamListInfo boundParams) {
ereport(NOTICE, errmsg("planner_hook_fn %p", handle->returns.PlannedStmt_value));
}
void _Omni_init(const omni_handle *handle) {
omni_hook planner_hook = {.type = omni_hook_planner,
.name = "omni_guard planner hook",
.fn = {.planner = planner_hook_fn},
.wrap = true};
handle->register_hook(handle, &planner_hook);
}
Inside the callback _Omni_init
, invoke allocate_shmem
method of omni_handle
type.
Example:
void _Omni_init(const omni_handle *handle) {
bool found;
int a = handle->allocate_shmem(handle, "shmem example using omni", sizeof(int), NULL, NULL, &found);
}
Inside the callback _Omni_deinit
, call deallocate_shmem
method of omni_handle
type.
Example:
TODO: to tests
void _Omni_deinit(const omni_handle *handle) {
handle->deallocate_shmem(handle, "shmem example using omni", NULL);
}
Inside the callback _Omni_init
, invoke declare_guc_variable
method of omni_handle
type.
void _Omni_init(const omni_handle *handle) {
omni_guc_variable guc_example_variable = {
.name = "guc_example_variable",
.long_desc = "Example variable to set GUC with omni",
.type = PGC_STRING,
.typed = {.string_val = {.boot_value = "hello"}},
.context = PGC_SIGHUP};
}
In general, starting background workers from an extension require postgres restart.
Inside the callback _Omni_init
, invoke request_bgworker_start
method of omni_handle
type.
request_bgworker_start
takes an argument of type BackgroundWorker
TODO: should the function be declared as PGDLLEXPORT or not?
PGDLLEXPORT void example_entry_point() {
elog(INFO, "do something useful here");
}
void _Omni_init(const omni_handle *handle) {
omni_bgworker_handle example_bgworker_handle = handle->request_bgworker_start(handle, {
.bgw_name = "example bgw worker from omni"
.bgw_type = "omni"
.bgw_function_name = "example_entry_point"
}, NULL);
}
Inside the callback _Omni_deinit
, invoke request_bgworker_termination
method of omni_handle
type.
void _Omni_deinit(const omni_handle *handle) {
if (example_bgworker_handle != NULL) {
handle->request_bgworker_termination(
handle,
example_bgworker_handle
);
}
}