LCOV - code coverage report
Current view: top level - src - db_file_transaction.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.7 % 42 36
Test Date: 2026-10-20 14:27:43 Functions: 100.0 % 4 4
Branches: 79.2 % 24 19

             Branch data     Line data    Source code
       1                 :             : #include "precizer.h"
       2                 :             : 
       3                 :             : /**
       4                 :             :  * @brief Start a batch before the main traversal saves a file record
       5                 :             :  *
       6                 :             :  * The batch uses the primary connection settings established by db_init().
       7                 :             :  * Later saves join the active batch without moving its deadline. Dry-run
       8                 :             :  * does not start transactions. Outside dry-run, the caller supplies a writable
       9                 :             :  * connection
      10                 :             :  *
      11                 :             :  * @return SUCCESS when a batch is ready or unnecessary, otherwise FAILURE
      12                 :             :  */
      13                 :        3610 : Return db_file_transaction_begin(void)
      14                 :             : {
      15                 :             :         /* Status returned by this function through provide()
      16                 :             :            Default value assumes successful completion */
      17                 :        3610 :         Return status = SUCCESS;
      18                 :             : 
      19         [ +  + ]:        3610 :         if(config->dry_run == true)
      20                 :             :         {
      21                 :         694 :                 provide(status);
      22                 :             :         }
      23                 :             : 
      24                 :             :         /*
      25                 :             :          * Reuse the current batch without starting another transaction or resetting
      26                 :             :          * its timer. Autocommit must remain disabled while the batch is active.
      27                 :             :          * If SQLite has ended the transaction (for example, after an automatic
      28                 :             :          * rollback), report failure to prevent further writes outside the batch
      29                 :             :          */
      30         [ +  + ]:        2916 :         if(config->file_transaction_active == true)
      31                 :             :         {
      32         [ -  + ]:        2597 :                 if(sqlite3_get_autocommit(config->db) != 0)
      33                 :             :                 {
      34                 :           0 :                         slog(ERROR,"File traversal transaction ended before commit\n");
      35                 :           0 :                         status = FAILURE;
      36                 :             :                 }
      37                 :             : 
      38                 :        2597 :                 provide(status);
      39                 :             :         }
      40                 :             : 
      41                 :             :         /* Use the primary connection settings established by db_init() */
      42                 :         319 :         const int rc = sqlite3_exec(config->db,"BEGIN IMMEDIATE;",NULL,NULL,NULL);
      43                 :             : 
      44         [ -  + ]:         319 :         if(rc != SQLITE_OK)
      45                 :             :         {
      46                 :           0 :                 log_sqlite_error(config->db,rc,NULL,"Failed to begin file traversal transaction");
      47                 :           0 :                 status = FAILURE;
      48                 :             :         } else {
      49                 :         319 :                 config->file_transaction_active = true;
      50                 :         319 :                 config->file_transaction_started_ns = cur_time_monotonic_ns();
      51                 :             :         }
      52                 :             : 
      53                 :         319 :         provide(status);
      54                 :             : }
      55                 :             : 
      56                 :             : /**
      57                 :             :  * @brief Commit the current batch of file records, if one is active
      58                 :             :  * @return SUCCESS after commit or when no batch is active, otherwise FAILURE
      59                 :             :  */
      60                 :         620 : Return db_file_transaction_commit(void)
      61                 :             : {
      62                 :             :         /* Status returned by this function through provide()
      63                 :             :            Default value assumes successful completion */
      64                 :         620 :         Return status = SUCCESS;
      65                 :             : 
      66         [ +  + ]:         620 :         if(config->file_transaction_active == true)
      67                 :             :         {
      68                 :         317 :                 const int rc = sqlite3_exec(config->db,"COMMIT;",NULL,NULL,NULL);
      69                 :             : 
      70         [ +  + ]:         317 :                 if(rc != SQLITE_OK)
      71                 :             :                 {
      72                 :           1 :                         log_sqlite_error(config->db,rc,NULL,"Failed to commit file traversal transaction");
      73                 :           1 :                         status = FAILURE;
      74                 :             :                 } else {
      75                 :         316 :                         config->file_transaction_active = false;
      76                 :             :                 }
      77                 :             :         }
      78                 :             : 
      79                 :         620 :         provide(status);
      80                 :             : }
      81                 :             : 
      82                 :             : /**
      83                 :             :  * @brief Commit pending file records when their shared interval has elapsed
      84                 :             :  * @param now_ns Current monotonic time in nanoseconds
      85                 :             :  * @return SUCCESS when the deadline was handled, otherwise FAILURE
      86                 :             :  */
      87                 :       24525 : Return db_file_transaction_check(const long long int now_ns)
      88                 :             : {
      89                 :             :         /* Status returned by this function through provide()
      90                 :             :            Default value assumes successful completion */
      91                 :       24525 :         Return status = SUCCESS;
      92                 :             : 
      93         [ +  + ]:       24525 :         if(config->file_transaction_active == true
      94         [ +  + ]:       24523 :                 && now_ns - config->file_transaction_started_ns >= DB_CHECKPOINT_INTERVAL_NS)
      95                 :             :         {
      96                 :           1 :                 call(db_file_transaction_commit());
      97                 :             :         }
      98                 :             : 
      99                 :       24525 :         provide(status);
     100                 :             : }
     101                 :             : 
     102                 :             : /**
     103                 :             :  * @brief Roll back any pending main-traversal transaction
     104                 :             :  *
     105                 :             :  * Does nothing when no file transaction is active. If SQLite already rolled
     106                 :             :  * back automatically, only the traversal transaction flag is cleared
     107                 :             :  *
     108                 :             :  * Database operations after traversal use the same connection settings
     109                 :             :  *
     110                 :             :  * @return Cleanup status, to be combined with the traversal result by the caller
     111                 :             :  */
     112                 :         615 : Return db_file_transaction_rollback(void)
     113                 :             : {
     114                 :             :         /* Status returned by this function through provide()
     115                 :             :            Default value assumes successful completion */
     116                 :         615 :         Return status = SUCCESS;
     117                 :             : 
     118         [ +  + ]:         615 :         if(config->file_transaction_active == true)
     119                 :             :         {
     120                 :             :                 /* SQLite may have rolled back automatically after an I/O or storage error */
     121         [ +  - ]:           3 :                 if(sqlite3_get_autocommit(config->db) == 0)
     122                 :             :                 {
     123                 :           3 :                         const int rc = sqlite3_exec(config->db,"ROLLBACK;",NULL,NULL,NULL);
     124                 :             : 
     125         [ -  + ]:           3 :                         if(rc != SQLITE_OK)
     126                 :             :                         {
     127                 :           0 :                                 log_sqlite_error(config->db,rc,NULL,"Failed to roll back file traversal transaction");
     128                 :           0 :                                 status = FAILURE;
     129                 :             :                         }
     130                 :             :                 }
     131                 :             : 
     132                 :             :                 /* Clear the flag after a successful rollback or if SQLite had already
     133                 :             :                    ended the transaction. Leave it set on failure because the transaction's
     134                 :             :                    state is uncertain */
     135         [ +  - ]:           3 :                 if(SUCCESS & status)
     136                 :             :                 {
     137                 :           3 :                         config->file_transaction_active = false;
     138                 :             :                 }
     139                 :             :         }
     140                 :             : 
     141                 :         615 :         provide(status);
     142                 :             : }
        

Generated by: LCOV version 2.0-1