Skip to content

Commit

Permalink
pgsys module (#67)
Browse files Browse the repository at this point in the history
Requires: #65 

With this change we split the C include and the `pgzx` into 2 modules:
- `pgzx_pgsys`: C includes and some custom C helpers
- `pgzx`: High level Zig utilities and abstractions.

The split is to prepare for code generation support. When generating Zig
code on the fly the generated code is imported as a module into `pgzx`,
but we also want the generated code to depend on the C includes. By
splitting out the C support we can have the generated module import
`pgsys` as a module dependency itself.

The change follows the pattern in
https://github.com/ziglang/zig/blob/master/test/standalone/dep_triangle/build.zig

We still re-export `pgsys` under `pgzx.c`.

Within `pgzx` we replace `const c = @import(...)` with `const pg =
@import("pgzx_pgsys");`. Now Postgres API usage is always prefixed with
`pg.*` instead of `c.*`, which is also more consistent on how we use the
namespaces ourselves and in the example extensions.
  • Loading branch information
urso authored Jun 22, 2024
1 parent 4d6d3e1 commit 466ac4c
Show file tree
Hide file tree
Showing 24 changed files with 583 additions and 550 deletions.
43 changes: 32 additions & 11 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,28 @@ pub fn build(b: *std.Build) void {
docs.dependOn(&build_docs.step);
}

// Reusable modules
const pgzx = blk: {
const module = b.addModule("pgzx", .{
.root_source_file = b.path("./src/pgzx.zig"),
// pgzx_pgsys module: C bindings to Postgres
const pgzx_pgsys = blk: {
const module = b.addModule("pgzx_pgsys", .{
.root_source_file = b.path("./src/pgzx/c.zig"),
.target = target,
.optimize = optimize,
});

// Internal C headers
module.addIncludePath(b.path("./src/pgzx/c/include/"));

// Postgres Headers
module.addIncludePath(.{
.cwd_relative = pgbuild.getIncludeServerDir(),
});
module.addIncludePath(.{
.cwd_relative = pgbuild.getIncludeDir(),
});
module.addLibraryPath(.{
.cwd_relative = pgbuild.getLibDir(),
});

// libpq support
module.addCSourceFiles(.{
.files = &[_][]const u8{
Expand All @@ -39,17 +50,24 @@ pub fn build(b: *std.Build) void {
"-I", pgbuild.getIncludeServerDir(),
},
});
module.addIncludePath(.{
.cwd_relative = pgbuild.getIncludeDir(),
});
module.addLibraryPath(.{
.cwd_relative = pgbuild.getLibDir(),
});
module.linkSystemLibrary("pq", .{});

break :blk module;
};

// pgzx: main project module.
// This module re-exports pgzx_pgsys, other generated modules, and utility functions.
const pgzx = blk: {
const module = b.addModule("pgzx", .{
.root_source_file = b.path("./src/pgzx.zig"),
.target = target,
.optimize = optimize,
});
module.addImport("pgzx_pgsys", pgzx_pgsys);

break :blk module;
};

// Unit test extension
const test_ext = blk: {
const test_options = b.addOptions();
Expand All @@ -63,9 +81,12 @@ pub fn build(b: *std.Build) void {
.link_libc = true,
.link_allow_shlib_undefined = true,
});
tests.lib.root_module.addOptions("build_options", test_options);

tests.lib.root_module.addIncludePath(b.path("./src/pgzx/c/include/"));

tests.lib.root_module.addImport("pgzx_pgsys", pgzx_pgsys);
tests.lib.root_module.addImport("pgzx", pgzx);
tests.lib.root_module.addOptions("build_options", test_options);

break :blk tests;
};
Expand Down
2 changes: 1 addition & 1 deletion src/pgzx.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
const std = @import("std");

// Export common set of postgres headers.
pub const c = @import("pgzx/c.zig");
pub const c = @import("pgzx_pgsys");

// Utility functions for working with the PostgreSQL C API.
pub const bgworker = @import("pgzx/bgworker.zig");
Expand Down
27 changes: 14 additions & 13 deletions src/pgzx/bgworker.zig
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
const std = @import("std");

const pgzx = @import("../pgzx.zig");
const c = @import("c.zig");
const pg = pgzx.c;

const elog = @import("elog.zig");
const err = @import("err.zig");
const lwlock = @import("lwlock.zig");

pub const BackgroundWorker = c.BackgroundWorker;
pub const BackgroundWorker = pg.BackgroundWorker;

pub const WorkerOptions = struct {
flags: c_int,
worker_type: ?[]const u8 = null,
start_time: c.BgWorkerStartTime = c.BgWorkerStart_RecoveryFinished,
start_time: pg.BgWorkerStartTime = pg.BgWorkerStart_RecoveryFinished,
restart_time: c_int = 1,
main_arg: c.Datum = 0,
main_arg: pg.Datum = 0,
extra: ?[]const u8 = null,
notify_pid: c.pid_t = 0,
notify_pid: pg.pid_t = 0,
};

pub fn register(
Expand All @@ -25,15 +26,15 @@ pub fn register(
options: WorkerOptions,
) void {
var bw = initBackgroundWorker(name, library_name, function_name, options);
c.RegisterBackgroundWorker(&bw);
pg.RegisterBackgroundWorker(&bw);
}

pub fn registerDynamic(
comptime name: []const u8,
comptime library_name: []const u8,
comptime function_name: []const u8,
options: WorkerOptions,
) !*c.BackgroundWorkerHandle {
) !*pg.BackgroundWorkerHandle {
std.log.debug("init background worker: {s} {s} {s}", .{
name,
library_name,
Expand All @@ -47,8 +48,8 @@ pub fn registerDynamic(
library_name,
function_name,
});
var handle: ?*c.BackgroundWorkerHandle = null;
const ok = c.RegisterDynamicBackgroundWorker(&bw, &handle);
var handle: ?*pg.BackgroundWorkerHandle = null;
const ok = pg.RegisterDynamicBackgroundWorker(&bw, &handle);
if (!ok) {
return err.PGError.FailStartBackgroundWorker;
}
Expand All @@ -66,8 +67,8 @@ fn initBackgroundWorker(
comptime library_name: []const u8,
comptime function_name: []const u8,
options: WorkerOptions,
) c.BackgroundWorker {
var bw = std.mem.zeroInit(c.BackgroundWorker, .{
) pg.BackgroundWorker {
var bw = std.mem.zeroInit(pg.BackgroundWorker, .{
.bgw_flags = options.flags,
.bgw_start_time = options.start_time,
.bgw_restart_time = options.restart_time,
Expand Down Expand Up @@ -110,8 +111,8 @@ pub inline fn sigFlagHandler(sig: *pgzx.intr.Signal) fn (c_int) callconv(.C) voi
pub fn finalizeSignal(arg: c_int) void {
_ = arg;
const save_errno = std.c._errno().*;
if (c.MyProc != null) {
c.SetLatch(&c.MyProc.*.procLatch);
if (pg.MyProc != null) {
pg.SetLatch(&pg.MyProc.*.procLatch);
}
std.c._errno().* = save_errno;
}
68 changes: 34 additions & 34 deletions src/pgzx/collections/dlist.zig
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! Postgres intrusive double linked list support.

const std = @import("std");
const c = @import("../c.zig");
const pg = @import("pgzx_pgsys");

fn initNode() c.dlist_node {
fn initNode() pg.dlist_node {
return .{ .prev = null, .next = null };
}

Expand All @@ -14,15 +14,15 @@ pub fn DList(comptime T: type, comptime node_field: std.meta.FieldEnum(T)) type
pub const Iterator = DListIter(T, node_field);
pub const descr = DListDescr(T, node_field);

list: c.dlist_head,
list: pg.dlist_head,

pub inline fn init() Self {
return .{ .list = .{ .head = initNode() } };
}

inline fn ensureInit(self: *Self) void {
if (self.list.head.next == null) {
c.dlist_init(&self.list);
pg.dlist_init(&self.list);
}
}

Expand All @@ -42,7 +42,7 @@ pub fn DList(comptime T: type, comptime node_field: std.meta.FieldEnum(T)) type
// The elemenst in `other` must be of type T and the same member node
// must have been used to insert the elements into `other`.
//
pub inline fn appendFromDList(self: *Self, other: *c.dlist_head) void {
pub inline fn appendFromDList(self: *Self, other: *pg.dlist_head) void {
appendDList(&self.list, other);
}

Expand All @@ -54,7 +54,7 @@ pub fn DList(comptime T: type, comptime node_field: std.meta.FieldEnum(T)) type
//
// The `other` list must be compatible with the current list. The
// element type and the node members must match the type of Self.
pub inline fn appendToDList(self: *const Self, other: *c.dlist_head) void {
pub inline fn appendToDList(self: *const Self, other: *pg.dlist_head) void {
appendDList(other, &self.list);
}

Expand All @@ -69,7 +69,7 @@ pub fn DList(comptime T: type, comptime node_field: std.meta.FieldEnum(T)) type
}
}

pub inline fn rawList(self: *Self) *c.dlist_head {
pub inline fn rawList(self: *Self) *pg.dlist_head {
return &self.list;
}

Expand All @@ -81,105 +81,105 @@ pub fn DList(comptime T: type, comptime node_field: std.meta.FieldEnum(T)) type
}

pub inline fn isEmpty(self: *const Self) bool {
return c.dlist_is_empty(&self.list);
return pg.dlist_is_empty(&self.list);
}

pub inline fn headNode(self: *const Self) *T {
if (self.isEmpty()) {
@panic("headNode on empty list");
}
const node = c.dlist_head_node(@constCast(&self.list));
const node = pg.dlist_head_node(@constCast(&self.list));
return descr.nodeParentPtr(node.?);
}

pub inline fn tailNode(self: *const Self) *T {
if (self.isEmpty()) {
@panic("tailNode on empty list");
}
const node = c.dlist_tail_node(@constCast(&self.list));
const node = pg.dlist_tail_node(@constCast(&self.list));
return descr.nodeParentPtr(node.?);
}

pub inline fn pushHead(self: *Self, node: *T) void {
c.dlist_push_head(&self.list, descr.nodePtr(node));
pg.dlist_push_head(&self.list, descr.nodePtr(node));
}

pub inline fn pushTail(self: *Self, node: *T) void {
c.dlist_push_tail(&self.list, descr.nodePtr(node));
pg.dlist_push_tail(&self.list, descr.nodePtr(node));
}

pub inline fn popHead(self: *Self) *T {
if (self.isEmpty()) {
@panic("popHead on empty list");
}
return descr.nodeParentPtr(c.dlist_pop_head_node(&self.list));
return descr.nodeParentPtr(pg.dlist_pop_head_node(&self.list));
}

pub inline fn popTail(self: *Self) *T {
if (self.isEmpty()) {
@panic("popTail on empty list");
}
const tail = c.dlist_tail_node(&self.list);
c.dlist_delete(tail);
const tail = pg.dlist_tail_node(&self.list);
pg.dlist_delete(tail);
return descr.nodeParentPtr(tail.?);
}

pub inline fn moveHead(self: *Self, node: *T) void {
c.dlist_move_head(&self.list, descr.nodePtr(node));
pg.dlist_move_head(&self.list, descr.nodePtr(node));
}

pub inline fn moveTail(self: *Self, node: *T) void {
c.dlist_move_tail(&self.list, descr.nodePtr(node));
pg.dlist_move_tail(&self.list, descr.nodePtr(node));
}

pub inline fn nextNode(self: *const Self, node: *T) *T {
return descr.nodeParentPtr(c.dlist_next_node(&self.list, descr.nodePtr(node)));
return descr.nodeParentPtr(pg.dlist_next_node(&self.list, descr.nodePtr(node)));
}

pub inline fn prevNode(self: *const Self, node: *T) *T {
return descr.nodeParentPtr(c.dlist_prev_node(&self.list, descr.nodePtr(node)));
return descr.nodeParentPtr(pg.dlist_prev_node(&self.list, descr.nodePtr(node)));
}

pub inline fn iterator(self: *const Self) Iterator {
return Iterator.init(&self.list);
}

pub inline fn insertAfter(node: *T, new_node: *T) void {
c.dlist_insert_after(descr.nodePtr(node), descr.nodePtr(new_node));
pg.dlist_insert_after(descr.nodePtr(node), descr.nodePtr(new_node));
}

pub inline fn insertBefore(node: *T, new_node: *T) void {
c.dlist_insert_before(descr.nodePtr(node), descr.nodePtr(new_node));
pg.dlist_insert_before(descr.nodePtr(node), descr.nodePtr(new_node));
}

pub inline fn delete(node: *T) void {
c.dlist_delete(descr.nodePtr(node));
pg.dlist_delete(descr.nodePtr(node));
}

pub inline fn deleteThorougly(node: *T) void {
c.dlist_delete_thoroughly(descr.nodePtr(node));
pg.dlist_delete_thoroughly(descr.nodePtr(node));
}

pub inline fn isDetached(node: *T) bool {
return c.dlist_is_detached(descr.nodePtr(node));
return pg.dlist_is_detached(descr.nodePtr(node));
}
};
}

fn appendDList(to: *c.dlist_head, from: *c.dlist_head) void {
if (c.dlist_is_empty(from)) {
fn appendDList(to: *pg.dlist_head, from: *pg.dlist_head) void {
if (pg.dlist_is_empty(from)) {
return;
}
if (to.head.next == null) {
c.dlist_init(to);
pg.dlist_init(to);
}

to.*.head.prev.*.next = from.*.head.next;
from.*.head.next.*.prev = to.*.head.prev;
from.*.head.prev.*.next = &to.*.head;
to.*.head.prev = from.*.head.prev;

c.dlist_init(from);
pg.dlist_init(from);
}

fn DListIter(comptime T: type, comptime node_field: std.meta.FieldEnum(T)) type {
Expand All @@ -188,9 +188,9 @@ fn DListIter(comptime T: type, comptime node_field: std.meta.FieldEnum(T)) type

const descr = DListDescr(T, node_field);

iter: c.dlist_iter,
iter: pg.dlist_iter,

pub fn init(list: *const c.dlist_head) Self {
pub fn init(list: *const pg.dlist_head) Self {
const end = &list.head;
return .{
.iter = .{
Expand All @@ -216,15 +216,15 @@ pub fn DListDescr(comptime T: type, comptime node_field: std.meta.FieldEnum(T))
return struct {
const node = std.meta.fieldInfo(T, node_field).name;

pub inline fn nodePtr(v: *T) *c.dlist_node {
pub inline fn nodePtr(v: *T) *pg.dlist_node {
return &@field(v, node);
}

pub inline fn nodeParentPtr(n: *c.dlist_node) *T {
pub inline fn nodeParentPtr(n: *pg.dlist_node) *T {
return @fieldParentPtr(node, n);
}

pub inline fn optNodeParentPtr(n: ?*c.dlist_node) ?*T {
pub inline fn optNodeParentPtr(n: ?*pg.dlist_node) ?*T {
return if (n) |p| nodeParentPtr(p) else null;
}
};
Expand All @@ -235,7 +235,7 @@ pub const TestSuite_DList = struct {

const T = struct {
value: u32,
node: c.dlist_node = initNode(),
node: pg.dlist_node = initNode(),
};

pub fn testEmpty() !void {
Expand Down
Loading

0 comments on commit 466ac4c

Please sign in to comment.