Skip to content

Commit 93ef1d7

Browse files
committed
Update
1 parent 25a6c5c commit 93ef1d7

File tree

8 files changed

+467
-238
lines changed

8 files changed

+467
-238
lines changed

.github/workflows/build.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ jobs:
3434
CMAKE_ARCH_FLAG: --preset=x86-windows
3535
- os: ubuntu-20.04
3636
arch: x64
37-
CMAKE_ARCH_FLAG: --preset=unix
37+
CMAKE_ARCH_FLAG: --preset=x64-linux
3838
- os: ubuntu-20.04
3939
arch: x86
40-
CMAKE_ARCH_FLAG: --preset=unix -DCMAKE_C_FLAGS="-m32" -DCMAKE_CXX_FLAGS="-m32" -DVCPKG_TARGET_TRIPLET=x86-linux
40+
CMAKE_ARCH_FLAG: --preset=x86-linux
4141
- os: macos-13
4242
arch: x64
43-
CMAKE_ARCH_FLAG: --preset=unix
43+
CMAKE_ARCH_FLAG: --preset=x64-macos
4444

4545
runs-on: ${{ matrix.os }}
4646

CMakePresets.json

+18-2
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,25 @@
2929
}
3030
},
3131
{
32-
"name": "unix",
32+
"name": "x64-linux",
3333
"inherits": "vcpkg",
34-
"generator": "Ninja"
34+
"generator": "Ninja",
35+
"architecture": "x64"
36+
},
37+
{
38+
"name": "x86-linux",
39+
"inherits": "vcpkg",
40+
"generator": "Ninja",
41+
"architecture": "x86"
42+
},
43+
{
44+
"name": "x64-macos",
45+
"inherits": "vcpkg",
46+
"generator": "Ninja",
47+
"architecture": "x64",
48+
"cacheVariables": {
49+
"VCPKG_TARGET_TRIPLET": "x64-osx"
50+
}
3551
}
3652
]
3753
}

source/async_postgres.hpp

+24-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
#pragma once
22

33
#include <GarrysMod/Lua/AutoReference.h>
4+
#include <GarrysMod/Lua/Interface.h>
45
#include <GarrysMod/Lua/LuaInterface.h>
56
#include <libpq-fe.h>
67

78
#include <algorithm>
89
#include <chrono>
910
#include <exception>
1011
#include <memory>
12+
#include <optional>
1113
#include <queue>
1214
#include <string_view>
1315
#include <variant>
@@ -49,20 +51,34 @@ namespace async_postgres {
4951
std::string command;
5052
};
5153

54+
struct ParameterizedCommand {
55+
std::string command;
56+
std::vector<std::string> values;
57+
};
58+
5259
struct Query {
53-
std::variant<SimpleCommand> command;
60+
std::variant<SimpleCommand, ParameterizedCommand> command;
5461
GLua::AutoReference callback;
5562
bool sent = false;
5663
bool flushed = false;
5764
};
5865

66+
struct ResetEvent {
67+
std::vector<GLua::AutoReference> callbacks;
68+
PostgresPollingStatusType status = PGRES_POLLING_WRITING;
69+
};
70+
5971
using PGconnPtr = std::unique_ptr<PGconn, decltype(&PQfinish)>;
6072

6173
struct Connection {
6274
PGconnPtr conn;
6375
GLua::AutoReference lua_table;
6476
std::queue<Query> queries;
77+
std::optional<ResetEvent> reset_event;
78+
bool receive_notifications =
79+
false; // enabled if on_notify lua field is set
6580

81+
Connection(GLua::ILuaInterface* lua, PGconnPtr&& conn);
6682
~Connection();
6783
};
6884

@@ -74,6 +90,10 @@ namespace async_postgres {
7490
GLua::AutoReference&& callback);
7591
void process_pending_connections(GLua::ILuaInterface* lua);
7692

93+
void reset(GLua::ILuaInterface* lua, Connection* state,
94+
GLua::AutoReference&& callback);
95+
void process_reset(GLua::ILuaInterface* lua, Connection* state);
96+
7797
// notifications.cpp
7898
void process_notifications(GLua::ILuaInterface* lua, Connection* state);
7999

@@ -83,6 +103,9 @@ namespace async_postgres {
83103
// result.cpp
84104
void create_result_table(GLua::ILuaInterface* lua, PGresult* result);
85105

106+
// misc.cpp
107+
void register_misc_connection_functions(GLua::ILuaInterface* lua);
108+
86109
// util.cpp
87110
std::string_view get_string(GLua::ILuaInterface* lua, int index = -1);
88111
void pcall(GLua::ILuaInterface* lua, int nargs, int nresults);

source/connection.cpp

+63-9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@ using namespace async_postgres;
44

55
std::vector<Connection*> async_postgres::connections = {};
66

7+
Connection::Connection(GLua::ILuaInterface* lua, PGconnPtr&& conn)
8+
: conn(std::move(conn)) {
9+
lua->CreateTable();
10+
this->lua_table = GLua::AutoReference(lua);
11+
12+
// add connection to global list
13+
connections.push_back(this);
14+
}
15+
16+
Connection::~Connection() {
17+
// remove connection from global list
18+
// so event loop doesn't try to process it
19+
connections.erase(std::find(connections.begin(), connections.end(), this));
20+
}
21+
722
struct ConnectionEvent {
823
PGconnPtr conn;
924
GLua::AutoReference callback;
@@ -47,22 +62,14 @@ void async_postgres::connect(GLua::ILuaInterface* lua, std::string_view url,
4762
inline bool poll_pending_connection(GLua::ILuaInterface* lua,
4863
ConnectionEvent& event) {
4964
if (!socket_is_ready(event.conn.get(), event.status)) {
50-
lua->Msg("socket is not ready (%s)\n",
51-
event.status == PGRES_POLLING_READING ? "reading" : "writing");
5265
return false;
5366
}
5467

5568
// TODO: handle reset
5669

5770
event.status = PQconnectPoll(event.conn.get());
58-
lua->Msg("status: %d (%d)\n", event.status, PQstatus(event.conn.get()));
5971
if (event.status == PGRES_POLLING_OK) {
60-
auto state = new Connection{std::move(event.conn)};
61-
62-
lua->CreateTable();
63-
state->lua_table = GLua::AutoReference(lua);
64-
65-
connections.push_back(state);
72+
auto state = new Connection(lua, std::move(event.conn));
6673

6774
event.callback.Push();
6875
lua->PushBool(true);
@@ -96,3 +103,50 @@ void async_postgres::process_pending_connections(GLua::ILuaInterface* lua) {
96103
}
97104
}
98105
}
106+
107+
void async_postgres::reset(GLua::ILuaInterface* lua, Connection* state,
108+
GLua::AutoReference&& callback) {
109+
if (!state->reset_event) {
110+
if (PQresetStart(state->conn.get()) == 0) {
111+
throw std::runtime_error(PQerrorMessage(state->conn.get()));
112+
}
113+
114+
state->reset_event = ResetEvent();
115+
}
116+
117+
if (callback) {
118+
state->reset_event->callbacks.push_back(std::move(callback));
119+
}
120+
}
121+
122+
void async_postgres::process_reset(GLua::ILuaInterface* lua,
123+
Connection* state) {
124+
if (!state->reset_event) {
125+
return;
126+
}
127+
128+
auto& event = state->reset_event.value();
129+
if (!socket_is_ready(state->conn.get(), state->reset_event->status)) {
130+
return;
131+
}
132+
133+
event.status = PQresetPoll(state->conn.get());
134+
if (event.status == PGRES_POLLING_OK) {
135+
for (auto& callback : event.callbacks) {
136+
callback.Push();
137+
lua->PushBool(true);
138+
pcall(lua, 1, 0);
139+
}
140+
141+
state->reset_event.reset();
142+
} else if (event.status == PGRES_POLLING_FAILED) {
143+
for (auto& callback : event.callbacks) {
144+
callback.Push();
145+
lua->PushBool(false);
146+
lua->PushString(PQerrorMessage(state->conn.get()));
147+
pcall(lua, 2, 0);
148+
}
149+
150+
state->reset_event.reset();
151+
}
152+
}

0 commit comments

Comments
 (0)