LCOV - code coverage report
Current view: top level - src - db_vacuum.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 75.4 % 57 43
Test Date: 2026-10-20 14:27:43 Functions: 100.0 % 1 1
Branches: 63.3 % 30 19

             Branch data     Line data    Source code
       1                 :             : #include "precizer.h"
       2                 :             : #include <errno.h>
       3                 :             : 
       4                 :             : /**
       5                 :             :  * @brief Rebuild a database and report the space saved and elapsed time
       6                 :             :  *
       7                 :             :  * The VACUUM command rebuilds the database file, repacking it into a minimal
       8                 :             :  * amount of disk space. File sizes are measured immediately before and after
       9                 :             :  * the SQL maintenance sequence, including its optimization steps. The reported
      10                 :             :  * percentage is relative to the initial file size and is negative if the file
      11                 :             :  * grows. An initially empty file has no defined percentage, reported as n/a
      12                 :             :  *
      13                 :             :  * @param[in] db_file_path Path to the database file to vacuum
      14                 :             :  * @return SUCCESS on completion or in dry-run mode, otherwise FAILURE
      15                 :             :  */
      16                 :         331 : Return db_vacuum(const char *db_file_path)
      17                 :             : {
      18                 :             :         /* Status returned by this function through provide()
      19                 :             :            Default value assumes successful completion */
      20                 :         331 :         Return status = SUCCESS;
      21                 :             : 
      22                 :         331 :         sqlite3 *db = NULL;
      23                 :         331 :         char *err_msg = NULL;
      24                 :         331 :         bool db_is_primary = false;
      25                 :         331 :         bool db_file_modified = false;
      26                 :         331 :         struct stat db_stat_before = {0};
      27                 :         331 :         struct stat db_stat_after = {0};
      28                 :             : 
      29                 :             :         /* Validate input parameters */
      30         [ -  + ]:         331 :         if(db_file_path == NULL)
      31                 :             :         {
      32                 :           0 :                 slog(ERROR,"Invalid input parameters: db_file_path\n");
      33                 :           0 :                 provide(FAILURE);
      34                 :             :         }
      35                 :             : 
      36         [ -  + ]:         331 :         if(config->dry_run == true)
      37                 :             :         {
      38                 :           0 :                 slog(TRACE,"Dry Run mode is enabled. The database doesn't require vacuuming\n");
      39                 :           0 :                 provide(status);
      40                 :             :         }
      41                 :             : 
      42         [ +  + ]:         331 :         if(strcmp(db_file_path,confstr(db_primary_file_path)) == 0)
      43                 :             :         {
      44                 :         316 :                 db_is_primary = true;
      45                 :             :         }
      46                 :             : 
      47                 :             :         /* Open database in safe mode */
      48                 :         331 :         int rc = sqlite3_open_v2(db_file_path,&db,SQLITE_OPEN_READWRITE,NULL);
      49                 :             : 
      50         [ -  + ]:         331 :         if(SQLITE_OK != rc)
      51                 :             :         {
      52                 :           0 :                 log_sqlite_error(db,rc,NULL,"Failed to open database");
      53                 :           0 :                 status = FAILURE;
      54                 :             :         }
      55                 :             : 
      56         [ +  - ]:         331 :         if(SUCCESS == status)
      57                 :             :         {
      58         [ -  + ]:         331 :                 if(stat(db_file_path,&db_stat_before) != 0)
      59                 :             :                 {
      60                 :           0 :                         slog(ERROR,"Cannot stat database %s before vacuuming: %s\n",db_file_path,strerror(errno));
      61                 :           0 :                         status = FAILURE;
      62                 :             :                 }
      63                 :             :         }
      64                 :             : 
      65         [ +  - ]:         331 :         if(SUCCESS == status)
      66                 :             :         {
      67                 :             :                 /* Create SQL statement */
      68                 :         331 :                 const char *sql =
      69                 :             :                         "PRAGMA analyze;"
      70                 :             :                         "PRAGMA optimize;"
      71                 :             :                         "VACUUM;"
      72                 :             :                         "PRAGMA analyze;"
      73                 :             :                         "PRAGMA optimize;";
      74                 :             : 
      75         [ +  + ]:         331 :                 if(db_is_primary == true)
      76                 :             :                 {
      77                 :         316 :                         slog(EVERY,"Start vacuuming the primary database…\n");
      78                 :             :                 } else {
      79                 :          15 :                         slog(EVERY,"Start vacuuming…\n");
      80                 :             :                 }
      81                 :             : 
      82                 :             :                 /* Execute SQL statement */
      83                 :         331 :                 const long long int vacuum_start_ns = cur_time_monotonic_ns();
      84                 :         331 :                 rc = sqlite3_exec(db,sql,NULL,NULL,&err_msg);
      85                 :         331 :                 long long int vacuum_elapsed_ns = cur_time_monotonic_ns() - vacuum_start_ns;
      86                 :             : 
      87         [ -  + ]:         331 :                 if(SQLITE_OK != rc)
      88                 :             :                 {
      89                 :             : 
      90                 :           0 :                         log_sqlite_error(db,rc,err_msg,"Can't execute vacuum");
      91                 :           0 :                         status = FAILURE;
      92                 :             : 
      93                 :             :                 } else {
      94                 :             : 
      95                 :         331 :                         db_file_modified = true;
      96                 :             : 
      97         [ -  + ]:         331 :                         if(stat(db_file_path,&db_stat_after) != 0)
      98                 :             :                         {
      99                 :           0 :                                 slog(ERROR,"Cannot stat database %s after vacuuming: %s\n",db_file_path,strerror(errno));
     100                 :           0 :                                 status = FAILURE;
     101                 :             :                         } else {
     102         [ -  + ]:         331 :                                 if(vacuum_elapsed_ns < 0LL)
     103                 :             :                                 {
     104                 :           0 :                                         vacuum_elapsed_ns = 0LL;
     105                 :             :                                 }
     106                 :             : 
     107                 :         331 :                                 char elapsed_string[50] = {0};
     108                 :         331 :                                 (void)form_date_r(vacuum_elapsed_ns,MAJOR_VIEW,elapsed_string,sizeof(elapsed_string));
     109                 :             : 
     110                 :         331 :                                 const char *db_label = "DB";
     111                 :             : 
     112         [ +  + ]:         331 :                                 if(db_is_primary == true)
     113                 :             :                                 {
     114                 :         316 :                                         db_label = "Primary DB";
     115                 :             :                                 }
     116                 :             : 
     117         [ +  - ]:         331 :                                 if(db_stat_before.st_size > 0)
     118                 :             :                                 {
     119                 :         331 :                                         const long double saved_percent =
     120                 :         331 :                                                 ((long double)db_stat_before.st_size - (long double)db_stat_after.st_size)
     121                 :         331 :                                                 * 100.0L / (long double)db_stat_before.st_size;
     122                 :             : 
     123                 :         331 :                                         slog(EVERY,"%s vacuumed: saved %.2Lf%%, elapsed %s\n",db_label,saved_percent,elapsed_string);
     124                 :             :                                 } else {
     125                 :           0 :                                         slog(EVERY,"%s vacuumed: saved n/a, elapsed %s\n",db_label,elapsed_string);
     126                 :             :                                 }
     127                 :             :                         }
     128                 :             :                 }
     129                 :             :         }
     130                 :             : 
     131         [ +  - ]:         331 :         if(db_file_modified == true)
     132                 :             :         {
     133                 :             :                 /**
     134                 :             :                  *
     135                 :             :                  * If the database being updated is the primary one, adjust the global
     136                 :             :                  * flag indicating that the main database file has been
     137                 :             :                  * modified (this will consequently update the file's ctime, mtime, and size)
     138                 :             :                  */
     139         [ +  + ]:         331 :                 if(db_is_primary == true)
     140                 :             :                 {
     141                 :             :                         /* Changes have been made to the database. Update
     142                 :             :                            this in the global variable value. */
     143                 :         316 :                         config->db_primary_file_modified = true;
     144                 :             :                 }
     145                 :             : 
     146                 :             :         }
     147                 :             : 
     148                 :             :         /* Cleanup */
     149                 :         331 :         call(db_close(db,&db_file_modified));
     150                 :             : 
     151                 :         331 :         provide(status);
     152                 :             : }
        

Generated by: LCOV version 2.0-1