Release partial SQL bootstrap records on allocation failures
This commit is contained in:
1 parent
99608de811
commit
26b5da6835
2 files changed
+171
-124
No files matched your search
@@ -1140,157 +1140,157 @@ struct TOPO_NODE* topo_node_sqlite_snapshot_load(sqlite3* db, struct TOPO_GROUPS
|
||||
}
|
||||
|
||||
struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* groups, uint64_t node_id) {
|
||||
if (!db || !groups) return NULL;
|
||||
if (!db || !groups || !groups->instance || groups->instance->topo_groups != groups) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "node load: invalid database/groups node=%016llx", (unsigned long long)node_id); return NULL;
|
||||
}
|
||||
struct TOPO_NODE* snapshot = topo_node_sqlite_snapshot_load(db, groups, node_id);
|
||||
if (snapshot) return snapshot;
|
||||
|
||||
struct TOPO_NODE* ni = u_calloc(1, sizeof(*ni));
|
||||
if (!ni) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "node load: allocation failed node=%016llx", (unsigned long long)node_id); return NULL; }
|
||||
sqlite3_stmt* s = NULL;
|
||||
uint8_t pubkey[32] = {0}, ed_pubkey[32] = {0};
|
||||
char* name = NULL;
|
||||
uint8_t client_type = 0;
|
||||
int found = 0;
|
||||
{
|
||||
sqlite3_stmt* s = NULL;
|
||||
if (sqlite3_prepare_v2(db, "SELECT name,x25519_pubkey,ed25519_pubkey,client_type FROM nodes WHERE node_id=?",
|
||||
-1, &s, NULL) == SQLITE_OK) {
|
||||
sqlite3_bind_int64(s, 1, (sqlite3_int64)node_id);
|
||||
if (sqlite3_step(s) == SQLITE_ROW) {
|
||||
const char* n = (const char*)sqlite3_column_text(s, 0);
|
||||
if (n) name = u_strdup(n);
|
||||
const void* pk = sqlite3_column_blob(s, 1);
|
||||
if (pk && sqlite3_column_bytes(s, 1) >= 32) memcpy(pubkey, pk, 32);
|
||||
const void* ep = sqlite3_column_blob(s, 2);
|
||||
if (ep && sqlite3_column_bytes(s, 2) >= 32) memcpy(ed_pubkey, ep, 32);
|
||||
client_type = (uint8_t)sqlite3_column_int(s, 3);
|
||||
found = 1;
|
||||
}
|
||||
sqlite3_finalize(s);
|
||||
}
|
||||
}
|
||||
if (!found) { u_free(name); return NULL; }
|
||||
|
||||
struct TOPO_ADDR4* v4_head = NULL; struct TOPO_ADDR4* v4_tail = NULL;
|
||||
struct TOPO_SOCKMETA4* m4_head = NULL; struct TOPO_SOCKMETA4* m4_tail = NULL;
|
||||
struct TOPO_ADDR6* v6_head = NULL; struct TOPO_ADDR6* v6_tail = NULL;
|
||||
struct TOPO_SOCKMETA6* m6_head = NULL; struct TOPO_SOCKMETA6* m6_tail = NULL;
|
||||
struct TOPO_REALITY_SOCK* r_head = NULL; struct TOPO_REALITY_SOCK* r_tail = NULL;
|
||||
{
|
||||
sqlite3_stmt* s = NULL;
|
||||
if (sqlite3_prepare_v2(db, "SELECT name,x25519_pubkey,ed25519_pubkey,client_type FROM nodes WHERE node_id=?",
|
||||
-1, &s, NULL) != SQLITE_OK) goto sql_failed;
|
||||
if (sqlite3_bind_int64(s, 1, (sqlite3_int64)node_id) != SQLITE_OK) goto sql_failed;
|
||||
int rc = sqlite3_step(s);
|
||||
if (rc == SQLITE_ROW) {
|
||||
const char* n = (const char*)sqlite3_column_text(s, 0);
|
||||
if (n) { name = u_strdup(n); if (!name) goto allocation_failed; }
|
||||
const void* pk = sqlite3_column_blob(s, 1);
|
||||
if (pk && sqlite3_column_bytes(s, 1) >= 32) memcpy(pubkey, pk, 32);
|
||||
const void* ep = sqlite3_column_blob(s, 2);
|
||||
if (ep && sqlite3_column_bytes(s, 2) >= 32) memcpy(ed_pubkey, ep, 32);
|
||||
client_type = (uint8_t)sqlite3_column_int(s, 3);
|
||||
found = 1;
|
||||
} else if (rc != SQLITE_DONE) goto sql_failed;
|
||||
sqlite3_finalize(s); s = NULL;
|
||||
}
|
||||
if (!found) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "node load: missing node=%016llx", (unsigned long long)node_id); goto failed; }
|
||||
|
||||
{
|
||||
if (sqlite3_prepare_v2(db,
|
||||
"SELECT address,port,addr_type,socket_id,protocol,config_type,nat_mapping,options,address_kind FROM node_addresses"
|
||||
" WHERE node_id=? AND family=4 ORDER BY addr_type",
|
||||
-1, &s, NULL) == SQLITE_OK) {
|
||||
sqlite3_bind_int64(s, 1, (sqlite3_int64)node_id);
|
||||
while (sqlite3_step(s) == SQLITE_ROW) {
|
||||
const void* addr = sqlite3_column_blob(s, 0);
|
||||
if (!addr || sqlite3_column_bytes(s, 0) < 4) continue;
|
||||
int port = sqlite3_column_int(s, 1);
|
||||
int sock_id_raw = sqlite3_column_int(s, 3);
|
||||
uint8_t sock_id = (uint8_t)sock_id_raw;
|
||||
uint8_t type = (uint8_t)sqlite3_column_int(s, 8);
|
||||
struct TOPO_ADDR4* a4 = memory_pool_alloc(groups->v4_addr_pool);
|
||||
if (!a4) continue;
|
||||
memset(a4, 0, sizeof(*a4));
|
||||
int proto = sqlite3_column_int(s, 4);
|
||||
memcpy(a4->addr, addr, 4); a4->port = (uint16_t)port;
|
||||
a4->type = type; a4->socket_id = sock_id; a4->protocol = (uint8_t)proto;
|
||||
if (!v4_head) v4_head = v4_tail = a4;
|
||||
else { v4_tail->next = a4; v4_tail = a4; }
|
||||
-1, &s, NULL) != SQLITE_OK) goto sql_failed;
|
||||
if (sqlite3_bind_int64(s, 1, (sqlite3_int64)node_id) != SQLITE_OK) goto sql_failed;
|
||||
int rc;
|
||||
while ((rc = sqlite3_step(s)) == SQLITE_ROW) {
|
||||
const void* addr = sqlite3_column_blob(s, 0);
|
||||
if (!addr || sqlite3_column_bytes(s, 0) < 4) continue;
|
||||
int port = sqlite3_column_int(s, 1);
|
||||
int sock_id_raw = sqlite3_column_int(s, 3);
|
||||
uint8_t sock_id = (uint8_t)sock_id_raw;
|
||||
uint8_t type = (uint8_t)sqlite3_column_int(s, 8);
|
||||
struct TOPO_ADDR4* a4 = memory_pool_alloc(groups->v4_addr_pool);
|
||||
if (!a4) goto allocation_failed;
|
||||
memset(a4, 0, sizeof(*a4));
|
||||
int proto = sqlite3_column_int(s, 4);
|
||||
memcpy(a4->addr, addr, 4); a4->port = (uint16_t)port;
|
||||
a4->type = type; a4->socket_id = sock_id; a4->protocol = (uint8_t)proto;
|
||||
if (!v4_head) v4_head = v4_tail = a4;
|
||||
else { v4_tail->next = a4; v4_tail = a4; }
|
||||
|
||||
struct TOPO_SOCKMETA4* ex = m4_head;
|
||||
while (ex && ex->id != sock_id) ex = ex->next;
|
||||
if (!ex) {
|
||||
struct TOPO_SOCKMETA4* m4 = memory_pool_alloc(groups->v4_sock_meta_pool);
|
||||
if (m4) {
|
||||
m4->id = sock_id;
|
||||
m4->config_type = (uint8_t)sqlite3_column_int(s, 5);
|
||||
/* Без подписанного snapshot профиль из SQL-проекции не считается доказательством. */
|
||||
memset(&m4->address_profile, 0, sizeof(m4->address_profile));
|
||||
m4->next = NULL;
|
||||
if (!m4_head) m4_head = m4_tail = m4;
|
||||
else { m4_tail->next = m4; m4_tail = m4; }
|
||||
}
|
||||
}
|
||||
if (sqlite3_column_type(s, 7) == SQLITE_BLOB
|
||||
&& sqlite3_column_bytes(s, 7) == TOPO_ADDR_REALITY_OPTS_SIZE
|
||||
&& (proto & TOPO_PROTO_REALITY)) {
|
||||
const struct TOPO_ADDR_REALITY_OPTS* o = (const struct TOPO_ADDR_REALITY_OPTS*)sqlite3_column_blob(s, 7);
|
||||
struct TOPO_REALITY_SOCK* r = u_calloc(1, sizeof(*r));
|
||||
if (r) {
|
||||
r->socket_id = sock_id;
|
||||
memcpy(r->short_id, o->short_id, 8);
|
||||
memcpy(r->server_pubkey, o->server_pubkey, 32);
|
||||
memcpy(r->version, o->version, 3);
|
||||
memcpy(r->server_name, o->server_name, TOPO_REALITY_SNAME_MAX);
|
||||
r->server_name[TOPO_REALITY_SNAME_MAX - 1] = 0;
|
||||
if (!r_head) r_head = r_tail = r;
|
||||
else { r_tail->next = r; r_tail = r; }
|
||||
}
|
||||
}
|
||||
struct TOPO_SOCKMETA4* ex = m4_head;
|
||||
while (ex && ex->id != sock_id) ex = ex->next;
|
||||
if (!ex) {
|
||||
struct TOPO_SOCKMETA4* m4 = memory_pool_alloc(groups->v4_sock_meta_pool);
|
||||
if (!m4) goto allocation_failed;
|
||||
m4->id = sock_id;
|
||||
m4->config_type = (uint8_t)sqlite3_column_int(s, 5);
|
||||
/* Без подписанного snapshot профиль из SQL-проекции не считается доказательством. */
|
||||
memset(&m4->address_profile, 0, sizeof(m4->address_profile));
|
||||
m4->next = NULL;
|
||||
if (!m4_head) m4_head = m4_tail = m4;
|
||||
else { m4_tail->next = m4; m4_tail = m4; }
|
||||
}
|
||||
if (sqlite3_column_type(s, 7) == SQLITE_BLOB
|
||||
&& sqlite3_column_bytes(s, 7) == TOPO_ADDR_REALITY_OPTS_SIZE
|
||||
&& (proto & TOPO_PROTO_REALITY)) {
|
||||
const struct TOPO_ADDR_REALITY_OPTS* o = (const struct TOPO_ADDR_REALITY_OPTS*)sqlite3_column_blob(s, 7);
|
||||
struct TOPO_REALITY_SOCK* r = u_calloc(1, sizeof(*r));
|
||||
if (!r) goto allocation_failed;
|
||||
r->socket_id = sock_id;
|
||||
memcpy(r->short_id, o->short_id, 8);
|
||||
memcpy(r->server_pubkey, o->server_pubkey, 32);
|
||||
memcpy(r->version, o->version, 3);
|
||||
memcpy(r->server_name, o->server_name, TOPO_REALITY_SNAME_MAX);
|
||||
r->server_name[TOPO_REALITY_SNAME_MAX - 1] = 0;
|
||||
if (!r_head) r_head = r_tail = r;
|
||||
else { r_tail->next = r; r_tail = r; }
|
||||
}
|
||||
sqlite3_finalize(s);
|
||||
}
|
||||
if (rc != SQLITE_DONE) goto sql_failed;
|
||||
sqlite3_finalize(s); s = NULL;
|
||||
}
|
||||
/* IPv6 addresses */
|
||||
struct TOPO_ADDR6* v6_head = NULL; struct TOPO_ADDR6* v6_tail = NULL;
|
||||
struct TOPO_SOCKMETA6* m6_head = NULL; struct TOPO_SOCKMETA6* m6_tail = NULL;
|
||||
{
|
||||
sqlite3_stmt* s = NULL;
|
||||
if (sqlite3_prepare_v2(db,
|
||||
"SELECT address,port,addr_type,socket_id,protocol,config_type,nat_mapping,options,address_kind FROM node_addresses"
|
||||
" WHERE node_id=? AND family=6 ORDER BY addr_type",
|
||||
-1, &s, NULL) == SQLITE_OK) {
|
||||
sqlite3_bind_int64(s, 1, (sqlite3_int64)node_id);
|
||||
while (sqlite3_step(s) == SQLITE_ROW) {
|
||||
const void* addr = sqlite3_column_blob(s, 0);
|
||||
if (!addr || sqlite3_column_bytes(s, 0) < 16) continue;
|
||||
int port = sqlite3_column_int(s, 1);
|
||||
int sock_id_raw = sqlite3_column_int(s, 3);
|
||||
uint8_t sock_id = (uint8_t)sock_id_raw;
|
||||
uint8_t type = (uint8_t)sqlite3_column_int(s, 8);
|
||||
struct TOPO_ADDR6* a6 = memory_pool_alloc(groups->v6_addr_pool);
|
||||
if (!a6) continue;
|
||||
memset(a6, 0, sizeof(*a6));
|
||||
int proto6 = sqlite3_column_int(s, 4);
|
||||
memcpy(a6->addr, addr, 16); a6->port = (uint16_t)port;
|
||||
a6->type = type; a6->socket_id = sock_id; a6->protocol = (uint8_t)proto6;
|
||||
if (!v6_head) v6_head = v6_tail = a6;
|
||||
else { v6_tail->next = a6; v6_tail = a6; }
|
||||
-1, &s, NULL) != SQLITE_OK) goto sql_failed;
|
||||
if (sqlite3_bind_int64(s, 1, (sqlite3_int64)node_id) != SQLITE_OK) goto sql_failed;
|
||||
int rc;
|
||||
while ((rc = sqlite3_step(s)) == SQLITE_ROW) {
|
||||
const void* addr = sqlite3_column_blob(s, 0);
|
||||
if (!addr || sqlite3_column_bytes(s, 0) < 16) continue;
|
||||
int port = sqlite3_column_int(s, 1);
|
||||
int sock_id_raw = sqlite3_column_int(s, 3);
|
||||
uint8_t sock_id = (uint8_t)sock_id_raw;
|
||||
uint8_t type = (uint8_t)sqlite3_column_int(s, 8);
|
||||
struct TOPO_ADDR6* a6 = memory_pool_alloc(groups->v6_addr_pool);
|
||||
if (!a6) goto allocation_failed;
|
||||
memset(a6, 0, sizeof(*a6));
|
||||
int proto6 = sqlite3_column_int(s, 4);
|
||||
memcpy(a6->addr, addr, 16); a6->port = (uint16_t)port;
|
||||
a6->type = type; a6->socket_id = sock_id; a6->protocol = (uint8_t)proto6;
|
||||
if (!v6_head) v6_head = v6_tail = a6;
|
||||
else { v6_tail->next = a6; v6_tail = a6; }
|
||||
|
||||
struct TOPO_SOCKMETA6* ex = m6_head;
|
||||
while (ex && ex->id != sock_id) ex = ex->next;
|
||||
if (!ex) {
|
||||
struct TOPO_SOCKMETA6* m6 = memory_pool_alloc(groups->v6_sock_meta_pool);
|
||||
if (m6) {
|
||||
m6->id = sock_id;
|
||||
m6->config_type = (uint8_t)sqlite3_column_int(s, 5);
|
||||
memset(&m6->address_profile, 0, sizeof(m6->address_profile));
|
||||
m6->next = NULL;
|
||||
if (!m6_head) m6_head = m6_tail = m6;
|
||||
else { m6_tail->next = m6; m6_tail = m6; }
|
||||
}
|
||||
}
|
||||
if (sqlite3_column_type(s, 7) == SQLITE_BLOB
|
||||
&& sqlite3_column_bytes(s, 7) == TOPO_ADDR_REALITY_OPTS_SIZE
|
||||
&& (proto6 & TOPO_PROTO_REALITY)) {
|
||||
const struct TOPO_ADDR_REALITY_OPTS* o = (const struct TOPO_ADDR_REALITY_OPTS*)sqlite3_column_blob(s, 7);
|
||||
struct TOPO_REALITY_SOCK* r = u_calloc(1, sizeof(*r));
|
||||
if (r) {
|
||||
r->socket_id = sock_id;
|
||||
memcpy(r->short_id, o->short_id, 8);
|
||||
memcpy(r->server_pubkey, o->server_pubkey, 32);
|
||||
memcpy(r->version, o->version, 3);
|
||||
memcpy(r->server_name, o->server_name, TOPO_REALITY_SNAME_MAX);
|
||||
r->server_name[TOPO_REALITY_SNAME_MAX - 1] = 0;
|
||||
if (!r_head) r_head = r_tail = r;
|
||||
else { r_tail->next = r; r_tail = r; }
|
||||
}
|
||||
}
|
||||
struct TOPO_SOCKMETA6* ex = m6_head;
|
||||
while (ex && ex->id != sock_id) ex = ex->next;
|
||||
if (!ex) {
|
||||
struct TOPO_SOCKMETA6* m6 = memory_pool_alloc(groups->v6_sock_meta_pool);
|
||||
if (!m6) goto allocation_failed;
|
||||
m6->id = sock_id;
|
||||
m6->config_type = (uint8_t)sqlite3_column_int(s, 5);
|
||||
memset(&m6->address_profile, 0, sizeof(m6->address_profile));
|
||||
m6->next = NULL;
|
||||
if (!m6_head) m6_head = m6_tail = m6;
|
||||
else { m6_tail->next = m6; m6_tail = m6; }
|
||||
}
|
||||
if (sqlite3_column_type(s, 7) == SQLITE_BLOB
|
||||
&& sqlite3_column_bytes(s, 7) == TOPO_ADDR_REALITY_OPTS_SIZE
|
||||
&& (proto6 & TOPO_PROTO_REALITY)) {
|
||||
const struct TOPO_ADDR_REALITY_OPTS* o = (const struct TOPO_ADDR_REALITY_OPTS*)sqlite3_column_blob(s, 7);
|
||||
struct TOPO_REALITY_SOCK* r = u_calloc(1, sizeof(*r));
|
||||
if (!r) goto allocation_failed;
|
||||
r->socket_id = sock_id;
|
||||
memcpy(r->short_id, o->short_id, 8);
|
||||
memcpy(r->server_pubkey, o->server_pubkey, 32);
|
||||
memcpy(r->version, o->version, 3);
|
||||
memcpy(r->server_name, o->server_name, TOPO_REALITY_SNAME_MAX);
|
||||
r->server_name[TOPO_REALITY_SNAME_MAX - 1] = 0;
|
||||
if (!r_head) r_head = r_tail = r;
|
||||
else { r_tail->next = r; r_tail = r; }
|
||||
}
|
||||
sqlite3_finalize(s);
|
||||
}
|
||||
if (rc != SQLITE_DONE) goto sql_failed;
|
||||
sqlite3_finalize(s); s = NULL;
|
||||
}
|
||||
if (!v4_head && !v6_head) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_BGP, "node load: no bootstrap addresses node=%016llx", (unsigned long long)node_id); goto failed;
|
||||
}
|
||||
if (!v4_head && !v6_head) { u_free(name); DEBUG_WARN(DEBUG_CATEGORY_BGP, "node_load: node 0x%016llx has no addresses (may be stub/seed — will retry when addresses arrive)", (unsigned long long)node_id); return NULL; }
|
||||
|
||||
struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE));
|
||||
if (!ni) { u_free(name); return NULL; }
|
||||
ni->node_id = node_id; ni->ver = 1; ni->group_ref_count = 0;
|
||||
ni->client_type = client_type;
|
||||
memcpy(ni->public_key, pubkey, 32); memcpy(ni->ed25519_public_key, ed_pubkey, 32);
|
||||
@@ -1306,6 +1306,18 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
|
||||
topo_list_count((struct _topo_head*)v4_head),
|
||||
topo_list_count((struct _topo_head*)v6_head));
|
||||
return ni;
|
||||
sql_failed:
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "node load SQL failed node=%016llx rc=%d: %s",
|
||||
(unsigned long long)node_id, sqlite3_extended_errcode(db), sqlite3_errmsg(db));
|
||||
goto failed;
|
||||
allocation_failed:
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "node load: bootstrap allocation failed node=%016llx", (unsigned long long)node_id);
|
||||
failed:
|
||||
sqlite3_finalize(s);
|
||||
ni->node_name = name; ni->v4_addrs = v4_head; ni->v4_sock_meta = m4_head;
|
||||
ni->v6_addrs = v6_head; ni->v6_sock_meta = m6_head; ni->reality_socks = r_head;
|
||||
topo_node_destroy(groups, ni);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int topo_node_sqlite_set_connected(sqlite3* db, const char* channel_id, uint64_t node_id, int connected) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string.h>
|
||||
#include "utun_instance.h"
|
||||
#include "routing_layer/topo_group.h"
|
||||
#include "routing_layer/topo_node_sqlite.h"
|
||||
#include "transport_layer/etcp.h"
|
||||
#include "../lib/debug_config.h"
|
||||
#include "../lib/mem.h"
|
||||
@@ -24,7 +25,7 @@ static unsigned fail_at, attempts, inside_pool;
|
||||
static int track_allocations;
|
||||
|
||||
static int allocation_fails(const char *where) {
|
||||
if (!track_allocations || !strstr(where, "topo_node.c:")) return 0;
|
||||
if (!track_allocations || (!strstr(where, "topo_node.c:") && !strstr(where, "topo_node_sqlite.c:"))) return 0;
|
||||
attempts++;
|
||||
if (attempts != fail_at) return 0;
|
||||
DEBUG_WARN(DEBUG_CATEGORY_BGP, "[fault] NODEINFO allocation %u rejected at %s", attempts, where);
|
||||
@@ -262,6 +263,39 @@ static void test_allocation_failures(struct wire_fixture *f) {
|
||||
fail_at = 0;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "[PASS] NODEINFO all %u allocation failures leave empty outputs and no live allocations", total);
|
||||
}
|
||||
|
||||
/* SQL bootstrap обязан освободить уже прочитанные адреса/Reality при отказе любого следующего выделения. */
|
||||
static void test_bootstrap_allocation_failures(struct wire_fixture *f) {
|
||||
fixture_packet(f, 0, 0);
|
||||
struct TOPO_NODE *node = NULL;
|
||||
assert(!topo_node_deserialize(&f->group, f->wire, f->length, &node, NULL, NULL, NULL, NULL));
|
||||
node->v4_addrs->protocol = node->v6_addrs->protocol = TOPO_PROTO_TCP | TOPO_PROTO_REALITY;
|
||||
sqlite3 *db = NULL;
|
||||
assert(sqlite3_open(":memory:", &db) == SQLITE_OK && !topo_node_sqlite_init(db));
|
||||
assert(!topo_node_sqlite_node_update_verified(db, node->node_id, "bootstrap", node->public_key, node->ed25519_public_key, 1, 1));
|
||||
assert(!topo_node_sqlite_addrs_put(db, node->node_id, node));
|
||||
attempts = 0; fail_at = 0; track_allocations = 1;
|
||||
struct TOPO_NODE *loaded = topo_node_sqlite_node_load(db, &f->groups, node->node_id);
|
||||
track_allocations = 0;
|
||||
assert(loaded && loaded->v4_addrs && loaded->v6_addrs && loaded->reality_socks && attempts > 8);
|
||||
unsigned total = attempts;
|
||||
topo_node_destroy(&f->groups, loaded);
|
||||
for (unsigned nth = 1; nth <= total; nth++) {
|
||||
size_t before = live_allocations();
|
||||
attempts = 0; fail_at = nth; track_allocations = 1;
|
||||
loaded = topo_node_sqlite_node_load(db, &f->groups, node->node_id);
|
||||
track_allocations = 0;
|
||||
assert(!loaded && attempts == nth && live_allocations() == before);
|
||||
assert(sqlite3_next_stmt(db, NULL) == NULL);
|
||||
}
|
||||
fail_at = 0;
|
||||
assert(sqlite3_exec(db, "DROP TABLE node_addresses", NULL, NULL, NULL) == SQLITE_OK);
|
||||
size_t before = live_allocations();
|
||||
assert(!topo_node_sqlite_node_load(db, &f->groups, node->node_id) && live_allocations() == before);
|
||||
assert(sqlite3_next_stmt(db, NULL) == NULL);
|
||||
topo_node_destroy(&f->groups, node); sqlite3_close(db);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "[PASS] SQL bootstrap: %u allocation failures and SQL failure leave no live objects/statements", total);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(void) {
|
||||
@@ -275,6 +309,7 @@ int main(void) {
|
||||
test_empty_and_arguments(&fixture);
|
||||
#ifdef __linux__
|
||||
test_allocation_failures(&fixture);
|
||||
test_bootstrap_allocation_failures(&fixture);
|
||||
#endif
|
||||
fixture_destroy(&fixture);
|
||||
assert(u_get_allocated_count() == before);
|
||||
|
||||
Reference in new issue
Block a user