Retain stable NAT results and compact the address database
This commit is contained in:
1 parent
e47ae480f5
commit
db8a5ee2df
2 files changed
+80
-42
No files matched your search
@@ -121,9 +121,7 @@ static int address_row_put(sqlite3_stmt *statement, struct TOPO_NODE *node, uint
|
||||
if (has_reality) sqlite3_bind_blob(statement, 10, &reality, sizeof(reality), SQLITE_STATIC);
|
||||
else sqlite3_bind_null(statement, 10);
|
||||
sqlite3_bind_int(statement, 11, kind); sqlite3_bind_int(statement, 12, profile->inbound);
|
||||
sqlite3_bind_int64(statement, 13, (sqlite3_int64)profile->evidence_id);
|
||||
sqlite3_bind_int64(statement, 14, (sqlite3_int64)profile->checked_at);
|
||||
sqlite3_bind_int(statement, 15, profile->source);
|
||||
sqlite3_bind_int(statement, 13, profile->source);
|
||||
int result = sqlite3_step(statement);
|
||||
sqlite3_reset(statement);
|
||||
if (result != SQLITE_DONE) {
|
||||
@@ -147,8 +145,8 @@ int topo_node_sqlite_addrs_put(sqlite3 *db, uint64_t node_id, struct TOPO_NODE *
|
||||
if (sqlite3_step(statement) != SQLITE_DONE) goto fail;
|
||||
sqlite3_finalize(statement); statement = NULL;
|
||||
if (sqlite3_prepare_v2(db, "INSERT INTO node_addresses(node_id,family,protocol,address,port,addr_type,config_type,"
|
||||
"nat_mapping,socket_id,options,address_kind,nat_inbound,nat_evidence,nat_checked,nat_source)"
|
||||
" VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", -1, &statement, NULL) != SQLITE_OK) goto fail;
|
||||
"nat_mapping,socket_id,options,address_kind,nat_inbound,nat_source)"
|
||||
" VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)", -1, &statement, NULL) != SQLITE_OK) goto fail;
|
||||
int written = 0;
|
||||
for (const struct TOPO_ADDR4 *address = node->v4_addrs; address; address = address->next) {
|
||||
uint8_t config;
|
||||
@@ -244,6 +242,7 @@ int topo_node_sqlite_init(sqlite3* db) {
|
||||
|
||||
/* Проекция адресов производная. Старый формат пересоздаём, не интерпретируя NAT_TYPE_* как новый профиль. */
|
||||
sqlite3_stmt *schema = NULL;
|
||||
int legacy_profile = 0;
|
||||
if (sqlite3_prepare_v2(db, "SELECT 1 FROM sqlite_master WHERE type='table' AND name='node_addresses'",
|
||||
-1, &schema, NULL) != SQLITE_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "address schema inspection failed: %s", sqlite3_errmsg(db)); return -1;
|
||||
@@ -252,7 +251,7 @@ int topo_node_sqlite_init(sqlite3* db) {
|
||||
sqlite3_finalize(schema); schema = NULL;
|
||||
if (exists) {
|
||||
int compatible = sqlite3_prepare_v2(db,
|
||||
"SELECT nat_mapping,nat_inbound,nat_evidence,nat_checked,nat_source,address_kind FROM node_addresses LIMIT 0",
|
||||
"SELECT nat_mapping,nat_inbound,nat_source,address_kind FROM node_addresses LIMIT 0",
|
||||
-1, &schema, NULL);
|
||||
sqlite3_finalize(schema);
|
||||
if (compatible == SQLITE_ERROR) {
|
||||
@@ -262,6 +261,17 @@ int topo_node_sqlite_init(sqlite3* db) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "old address projection reset; signed NODEINFO will rebuild endpoint profiles");
|
||||
} else if (compatible != SQLITE_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "address schema read failed: %s", sqlite3_errmsg(db)); return -1;
|
||||
} else {
|
||||
if (sqlite3_prepare_v2(db, "SELECT count(*) FROM pragma_table_info('node_addresses')"
|
||||
" WHERE name IN ('nat_evidence','nat_checked')", -1, &schema, NULL) != SQLITE_OK ||
|
||||
sqlite3_step(schema) != SQLITE_ROW) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "address profile schema inspection failed: %s", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(schema); return -1;
|
||||
}
|
||||
int fields = sqlite3_column_int(schema, 0);
|
||||
sqlite3_finalize(schema); schema = NULL;
|
||||
if (fields == 1) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "incomplete legacy NAT profile schema"); return -1; }
|
||||
legacy_profile = fields == 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,8 +302,6 @@ int topo_node_sqlite_init(sqlite3* db) {
|
||||
" config_type INTEGER DEFAULT 0,"
|
||||
" nat_mapping INTEGER NOT NULL DEFAULT 0,"
|
||||
" nat_inbound INTEGER NOT NULL DEFAULT 0,"
|
||||
" nat_evidence INTEGER NOT NULL DEFAULT 0,"
|
||||
" nat_checked INTEGER NOT NULL DEFAULT 0,"
|
||||
" nat_source INTEGER NOT NULL DEFAULT 0,"
|
||||
" address_kind INTEGER NOT NULL DEFAULT 0,"
|
||||
" socket_id INTEGER NOT NULL DEFAULT 0,"
|
||||
@@ -331,6 +339,24 @@ int topo_node_sqlite_init(sqlite3* db) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Старые подписи непригодны; адреса и максимальные версии остаются для bootstrap и новой публикации. */
|
||||
if (legacy_profile) {
|
||||
const char *migration = "SAVEPOINT compact_nat_profile;"
|
||||
"ALTER TABLE node_addresses DROP COLUMN nat_evidence;"
|
||||
"ALTER TABLE node_addresses DROP COLUMN nat_checked;"
|
||||
"UPDATE node_addresses SET nat_mapping=0,nat_inbound=0,nat_source=0,"
|
||||
"addr_type=CASE WHEN addr_type=0 OR config_type IN (3,4) THEN 0 ELSE 4 END;"
|
||||
"UPDATE node_snapshots SET record=X'';"
|
||||
"RELEASE compact_nat_profile;";
|
||||
if (sqlite3_exec(db, migration, NULL, NULL, NULL) != SQLITE_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "compact NAT profile migration failed: %s", sqlite3_errmsg(db));
|
||||
if (sqlite3_exec(db, "ROLLBACK TO compact_nat_profile; RELEASE compact_nat_profile", NULL, NULL, NULL) != SQLITE_OK)
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "compact NAT profile migration rollback failed: %s", sqlite3_errmsg(db));
|
||||
return -1;
|
||||
}
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT profile compacted to mapping/inbound/source; bootstrap addresses and node versions preserved");
|
||||
}
|
||||
|
||||
/* migration: добавить колонку options в уже существующую node_addresses (idempotent) */
|
||||
{
|
||||
sqlite3_stmt* cs = NULL;
|
||||
@@ -1033,7 +1059,9 @@ struct TOPO_NODE* topo_node_sqlite_snapshot_load(sqlite3* db, struct TOPO_GROUPS
|
||||
struct TOPO_GROUP group = { .instance = groups->instance };
|
||||
const uint8_t* data = sqlite3_column_blob(stmt, 0);
|
||||
int len = sqlite3_column_bytes(stmt, 0);
|
||||
if (topo_node_deserialize(&group, data, (size_t)len, &ni, NULL, NULL, NULL, NULL) < 0 ||
|
||||
if (!len) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "snapshot invalidated by format change node=%016llx", (unsigned long long)node_id);
|
||||
} else if (topo_node_deserialize(&group, data, (size_t)len, &ni, NULL, NULL, NULL, NULL) < 0 ||
|
||||
!ni || ni->node_id != node_id || topo_node_verify(ni) < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid persisted snapshot node=%016llx", (unsigned long long)node_id);
|
||||
topo_node_destroy(groups, ni); ni = NULL;
|
||||
|
||||
Reference in new issue
Block a user