#include #include #include #include #include "route_node_lmdb.h" #include "route_bgp.h" #include "../lib/debug_config.h" #include "../lib/mem.h" #define NODEINFO_DB_MAPSIZE (10UL * 1024 * 1024) int route_node_lmdb_init(struct ROUTE_BGP* bgp, const char* db_path) { if (!bgp || !db_path || !db_path[0]) return -1; int rc = mdb_env_create(&bgp->nodeinfo_env); if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_create failed: %s", mdb_strerror(rc)); return -1; } rc = mdb_env_set_mapsize(bgp->nodeinfo_env, NODEINFO_DB_MAPSIZE); if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_set_mapsize failed: %s", mdb_strerror(rc)); mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; return -1; } rc = mdb_env_set_maxdbs(bgp->nodeinfo_env, 2); if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_set_maxdbs failed: %s", mdb_strerror(rc)); mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; return -1; } rc = mdb_env_open(bgp->nodeinfo_env, db_path, 0, 0644); if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_open(%s) failed: %s", db_path, mdb_strerror(rc)); mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; return -1; } MDB_txn* txn = NULL; rc = mdb_txn_begin(bgp->nodeinfo_env, NULL, 0, &txn); if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_txn_begin failed: %s", mdb_strerror(rc)); mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; return -1; } rc = mdb_dbi_open(txn, "nodeinfo", MDB_CREATE, &bgp->nodeinfo_dbi); if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_dbi_open(nodeinfo) failed: %s", mdb_strerror(rc)); mdb_txn_abort(txn); mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; return -1; } rc = mdb_txn_commit(txn); if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_txn_commit failed: %s", mdb_strerror(rc)); mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; return -1; } DEBUG_INFO(DEBUG_CATEGORY_BGP, "LMDB nodeinfo database opened: %s", db_path); return 0; } void route_node_lmdb_destroy(struct ROUTE_BGP* bgp) { if (!bgp) return; if (bgp->nodeinfo_env) { mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; DEBUG_INFO(DEBUG_CATEGORY_BGP, "LMDB nodeinfo database closed"); } } int route_node_lmdb_put(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq) { if (!bgp || !bgp->nodeinfo_env || !nq) return -1; int dyn_size = nodeinfo_dyn_size(&nq->node); size_t val_size = sizeof(struct NODEINFO) + dyn_size; MDB_val key, data; key.mv_size = 8; key.mv_data = &nq->node.node_id; data.mv_size = val_size; data.mv_data = (void*)&nq->node; MDB_txn* txn = NULL; int rc = mdb_txn_begin(bgp->nodeinfo_env, NULL, 0, &txn); if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB put mdb_txn_begin failed: %s", mdb_strerror(rc)); return -1; } rc = mdb_put(txn, bgp->nodeinfo_dbi, &key, &data, 0); if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_put node %016llx failed: %s", (unsigned long long)nq->node.node_id, mdb_strerror(rc)); mdb_txn_abort(txn); return -1; } rc = mdb_txn_commit(txn); if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB put mdb_txn_commit failed: %s", mdb_strerror(rc)); return -1; } return 0; } int route_node_lmdb_del(struct ROUTE_BGP* bgp, uint64_t node_id) { if (!bgp || !bgp->nodeinfo_env) return -1; MDB_val key; key.mv_size = 8; key.mv_data = &node_id; MDB_txn* txn = NULL; int rc = mdb_txn_begin(bgp->nodeinfo_env, NULL, 0, &txn); if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB del mdb_txn_begin failed: %s", mdb_strerror(rc)); return -1; } rc = mdb_del(txn, bgp->nodeinfo_dbi, &key, NULL); if (rc != MDB_SUCCESS && rc != MDB_NOTFOUND) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_del node %016llx failed: %s", (unsigned long long)node_id, mdb_strerror(rc)); mdb_txn_abort(txn); return -1; } rc = mdb_txn_commit(txn); if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB del mdb_txn_commit failed: %s", mdb_strerror(rc)); return -1; } return 0; }