@@ -561,6 +561,109 @@ static void close_env(int do_close_dbi)
561561 memset (& walk_read , 0 , sizeof (walk_read ));
562562}
563563
564+ /*
565+ * log_lmdb_state - log LMDB map, named DB, and reader-table state.
566+ * @priority: syslog priority used for the diagnostic lines.
567+ * @context: short description of the operation being diagnosed.
568+ * @lmdb_rc: LMDB return code that triggered the diagnostic, or 0.
569+ *
570+ * LMDB map pressure follows the environment high-water mark, not just the
571+ * current named database page count. Rebuilding a steady set of trust entries
572+ * can still run out of map space when old reader transactions keep deleted
573+ * pages from being reused. These diagnostics are intentionally grouped around
574+ * failures and size checks so the logs show active DB pages, allocated pages,
575+ * the last transaction id, and reader-table pressure together.
576+ *
577+ * Returns: none.
578+ */
579+ static void log_lmdb_state (int priority , const char * context , int lmdb_rc )
580+ {
581+ MDB_envinfo info ;
582+ MDB_stat stat ;
583+ MDB_txn * txn = NULL ;
584+ const char * where = context ? context : "unknown operation" ;
585+ size_t page_size = 4096 ;
586+ size_t map_pages = 0 ;
587+ size_t allocated_pages = 0 ;
588+ size_t db_pages = 0 ;
589+ int stale_readers = 0 ;
590+ int reader_rc ;
591+ int stat_rc = 0 ;
592+ int rc ;
593+
594+ if (env == NULL ) {
595+ msg (priority , "LMDB state after %s: environment is closed" ,
596+ where );
597+ return ;
598+ }
599+
600+ rc = mdb_env_info (env , & info );
601+ if (rc ) {
602+ msg (priority , "LMDB state after %s: mdb_env_info failed: %s" ,
603+ where , mdb_strerror (rc ));
604+ return ;
605+ }
606+
607+ reader_rc = mdb_reader_check (env , & stale_readers );
608+
609+ if (dbi_init ) {
610+ stat_rc = mdb_txn_begin (env , NULL , MDB_RDONLY , & txn );
611+ if (stat_rc == 0 ) {
612+ stat_rc = mdb_stat (txn , dbi , & stat );
613+ mdb_txn_abort (txn );
614+ }
615+ } else {
616+ stat_rc = EINVAL ;
617+ }
618+
619+ if (stat_rc == 0 ) {
620+ page_size = stat .ms_psize ;
621+ db_pages = stat .ms_branch_pages + stat .ms_leaf_pages +
622+ stat .ms_overflow_pages ;
623+ }
624+
625+ if (page_size )
626+ map_pages = info .me_mapsize / page_size ;
627+ allocated_pages = info .me_last_pgno + 1 ;
628+
629+ if (lmdb_rc )
630+ msg (priority , "LMDB state after %s: error=%s (%d)" ,
631+ where , mdb_strerror (lmdb_rc ), lmdb_rc );
632+
633+ msg (priority ,
634+ "LMDB env after %s: map=%zu MiB pages=%zu "
635+ "allocated=%zu (%zu%%) last_pgno=%zu txnid=%zu" ,
636+ where , info .me_mapsize / MEGABYTE , map_pages , allocated_pages ,
637+ map_pages ? (100 * allocated_pages ) / map_pages : 0 ,
638+ info .me_last_pgno , info .me_last_txnid );
639+
640+ if (stat_rc == 0 ) {
641+ msg (priority ,
642+ "LMDB db after %s: entries=%zu pages=%zu (%zu%%) "
643+ "branch=%zu leaf=%zu overflow=%zu depth=%u page_size=%zu" ,
644+ where , stat .ms_entries , db_pages ,
645+ map_pages ? (100 * db_pages ) / map_pages : 0 ,
646+ stat .ms_branch_pages , stat .ms_leaf_pages ,
647+ stat .ms_overflow_pages , stat .ms_depth , page_size );
648+ } else {
649+ msg (priority , "LMDB db after %s: stat unavailable: %s" ,
650+ where , mdb_strerror (stat_rc ));
651+ }
652+
653+ if (reader_rc ) {
654+ msg (priority ,
655+ "LMDB readers after %s: reader_check failed: %s slots_used=%u max=%u" ,
656+ where , mdb_strerror (reader_rc ), info .me_numreaders ,
657+ info .me_maxreaders );
658+ } else {
659+ msg (priority ,
660+ "LMDB readers after %s: slots_used=%u max=%u "
661+ "stale_cleared=%d configured_max=%u" ,
662+ where , info .me_numreaders , info .me_maxreaders ,
663+ stale_readers , db_max_readers );
664+ }
665+ }
666+
564667static void close_db (int do_report )
565668{
566669 if (do_report ) {
@@ -600,6 +703,23 @@ static void check_db_size(const conf_t *config)
600703 mdb_env_info (env , & st );
601704 max_pages = st .me_mapsize / size ;
602705 unsigned long percent = max_pages ? (100 * pages )/max_pages : 0 ;
706+ unsigned long allocated = st .me_last_pgno + 1 ;
707+ unsigned long allocated_percent =
708+ max_pages ? (100 * allocated )/max_pages : 0 ;
709+
710+ // Active DB pages can stay steady while LMDB's high-water mark grows
711+ // if readers pin old pages across repeated rebuilds.
712+ msg (LOG_DEBUG ,
713+ "Trust database active pages: %lu (%lu%%), allocated pages: %lu (%lu%%)" ,
714+ pages , percent , allocated , allocated_percent );
715+ if (allocated_percent > 85 && allocated_percent > percent ) {
716+ msg (LOG_WARNING ,
717+ "Trust database LMDB map high-water at %lu%% capacity "
718+ "while active DB pages are at %lu%%" ,
719+ allocated_percent , percent );
720+ log_lmdb_state (LOG_WARNING , "trust database size check" , 0 );
721+ }
722+
603723 if (percent > 85 ) {
604724 if (config -> do_audit_db_sizing )
605725 msg (LOG_WARNING , "Trust database at %lu%% capacity - "
@@ -920,14 +1040,19 @@ static int write_db(const char *idx, size_t idx_len, const char *data)
9201040 value .mv_size = strlen (data );
9211041
9221042 if ((rc = mdb_put (txn , dbi , & key , & value , 0 ))) {
923- msg (LOG_ERR , "%s" , mdb_strerror (rc ));
9241043 abort_transaction (txn );
1044+ msg (LOG_ERR , "mdb_put failed while writing trust DB: %s" ,
1045+ mdb_strerror (rc ));
1046+ log_lmdb_state (LOG_ERR , "trust DB write" , rc );
9251047 ret_val = (rc == MDB_MAP_FULL ) ? WRITE_DB_MAP_FULL : 3 ;
9261048 goto out ;
9271049 }
9281050
9291051 if ((rc = mdb_txn_commit (txn ))) {
930- msg (LOG_ERR , "%s" , mdb_strerror (rc ));
1052+ msg (LOG_ERR ,
1053+ "mdb_txn_commit failed after writing trust DB: %s" ,
1054+ mdb_strerror (rc ));
1055+ log_lmdb_state (LOG_ERR , "trust DB write commit" , rc );
9311056 ret_val = (rc == MDB_MAP_FULL ) ? WRITE_DB_MAP_FULL : 4 ;
9321057 goto out ;
9331058 }
@@ -1213,8 +1338,13 @@ static int delete_all_entries_db()
12131338 int rc = 0 ;
12141339 MDB_txn * txn ;
12151340
1216- if (mdb_txn_begin (env , NULL , 0 , & txn ))
1341+ rc = mdb_txn_begin (env , NULL , 0 , & txn );
1342+ if (rc ) {
1343+ msg (LOG_ERR , "mdb_txn_begin failed before trust DB delete: %s" ,
1344+ mdb_strerror (rc ));
1345+ log_lmdb_state (LOG_ERR , "trust DB delete begin" , rc );
12171346 return 1 ;
1347+ }
12181348
12191349 if (open_dbi (txn )) {
12201350 abort_transaction (txn );
@@ -1223,17 +1353,21 @@ static int delete_all_entries_db()
12231353
12241354 // 0 -> delete , 1 -> delete and close
12251355 if ((rc = mdb_drop (txn , dbi , 0 ))) {
1226- msg (LOG_DEBUG , "mdb_drop -> %s" , mdb_strerror (rc ));
12271356 abort_transaction (txn );
1357+ msg (LOG_ERR , "mdb_drop failed while clearing trust DB: %s" ,
1358+ mdb_strerror (rc ));
1359+ log_lmdb_state (LOG_ERR , "trust DB delete" , rc );
12281360 return rc == MDB_MAP_FULL ? WRITE_DB_MAP_FULL : 3 ;
12291361 }
12301362
12311363 if ((rc = mdb_txn_commit (txn ))) {
12321364 if (rc == MDB_MAP_FULL )
1233- msg (LOG_ERR , "db_max_size needs to be increased" );
1365+ msg (LOG_ERR ,
1366+ "mdb_txn_commit hit MDB_MAP_FULL while clearing trust DB" );
12341367 else
1235- msg (LOG_DEBUG , "mdb_txn_commit -> %s" ,
1368+ msg (LOG_ERR , "mdb_txn_commit while clearing trust DB: %s" ,
12361369 mdb_strerror (rc ));
1370+ log_lmdb_state (LOG_ERR , "trust DB delete commit" , rc );
12371371 return rc == MDB_MAP_FULL ? WRITE_DB_MAP_FULL : 4 ;
12381372 }
12391373
0 commit comments