utils/history/cleanup.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following functions.
  1. process_arguments
  2. get_max_serial
  3. delete_serials
  4. cleanup_history
  5. delete_last
  6. set_end_timestamp
  7. main

   1 /***************************************
   2   $Revision: 1.1 $
   3 
   4   Cleanup.  cleanup.c - whois DB clean up.
   5 
   6   Status: NOT REVIEWED, TESTED, COMPLETE
   7 
   8   Implementation by: Tiago Antao
   9 
  10   ******************/ /******************
  11   Copyright (c) 2002               RIPE NCC
  12  
  13   All Rights Reserved
  14   
  15   Permission to use, copy, modify, and distribute this software and its
  16   documentation for any purpose and without fee is hereby granted,
  17   provided that the above copyright notice appear in all copies and that
  18   both that copyright notice and this permission notice appear in
  19   supporting documentation, and that the name of the author not be
  20   used in advertising or publicity pertaining to distribution of the
  21   software without specific, written prior permission.
  22 
  23   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  24   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  25   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  26   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  27   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  28   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  29   ***************************************/
  30 
  31 
  32 #include <stdio.h>
  33 #include <stdlib.h>
  34 #include <time.h>
  35 #include <rip.h>
  36 #include "miniconf.h"
  37 #include "dbsupport.h"
  38 #include "aconf.h"
  39 
  40 long max_serial = 0;
  41 long end_time = 0;
  42 
  43 void process_arguments(int argv, char** argc) {
     /* [<][>][^][v][top][bottom][index][help] */
  44   if (argv != 1 ) {
  45     printf("Usage: %s\n", argc[0]);
  46     exit(1);
  47   }
  48 
  49 }
  50 
  51 /*
  52   get_max_serial: gets max serial that can be deleted.
  53 
  54   This is somewhat tricky because of deletes in last. A join cannot be
  55   made safely, so:
  56   when determining the serial via timestamp:
  57     when joining with history ignore serials with op=DELETE
  58     when joining with last consider only object='' and ignore sequence.
  59 
  60   returns the max of the 2 joins.
  61 */
  62 void get_max_serial() {
     /* [<][>][^][v][top][bottom][index][help] */
  63   SQ_result_set_t* rs;
  64   SQ_row_t*        row;
  65   char             query[1000];
  66   long             last_serial;
  67 
  68   sprintf(query,
  69           "SELECT max(serials.serial_id) "
  70           "  FROM serials, history "
  71           " WHERE serials.object_id=history.object_id "
  72           "   AND serials.sequence_id=history.sequence_id "
  73           "   AND timestamp<%ld "
  74           "   AND operation=1",
  75           end_time);
  76   SQ_execute_query(RIPE_conn, query, &rs);
  77   row = SQ_row_next(rs);
  78   if (row != NULL) {
  79     if (SQ_get_column_int(rs, row, 0, &max_serial) != 0) {
  80       max_serial = 0;
  81     }
  82   }
  83   SQ_free_result(rs);
  84 
  85   sprintf(query,
  86           "SELECT max(serials.serial_id) "
  87           "  FROM serials, last "
  88           " WHERE last.object_id=serials.object_id "
  89           //"   AND s.sequence_id=h.sequence_id "
  90           "   AND timestamp<=%ld "
  91           "   AND object=''",
  92           end_time);
  93   SQ_execute_query(RIPE_conn, query, &rs);
  94   row = SQ_row_next(rs);
  95   if (row != NULL) {
  96     if (SQ_get_column_int(rs, row, 0, &last_serial) == 0) {
  97       if (last_serial>max_serial) {
  98         max_serial = last_serial;
  99       }
 100     }
 101   }
 102   //printf ("max serial: %ld\n", max_serial);
 103   SQ_free_result(rs);
 104 
 105 
 106   //If all serials are to be deleted then preserve 1 for mirror ref
 107   sprintf(query,
 108           "SELECT max(serial_id) "
 109           "  FROM serials ");
 110   SQ_execute_query(RIPE_conn, query, &rs);
 111   row = SQ_row_next(rs);
 112   if (row != NULL) {
 113     if (SQ_get_column_int(rs, row, 0, &last_serial) == 0) {
 114       if (last_serial == max_serial) {
 115         max_serial = max_serial - 1;
 116       }
 117     }
 118   }
 119   //printf ("max serial: %ld\n", max_serial);
 120   SQ_free_result(rs);
 121 }
 122 
 123 /*
 124   delete_serials: delete serials referencing old operations.
 125 
 126   max_serial was previously computed on get_max_serial
 127  */
 128 void delete_serials() {
     /* [<][>][^][v][top][bottom][index][help] */
 129   char delete_query[200];
 130 
 131   sprintf(delete_query,
 132           "DELETE FROM serials "
 133           " WHERE serial_id<=%ld",
 134           max_serial);
 135   SQ_execute_query(RIPE_conn, delete_query, NULL);
 136 }
 137 
 138 /*
 139   cleanup_history: cleans the history table.
 140 
 141   A blind cleanup cannot be done as a record with an old timestamp might
 142   be referenced in a newer delete (a delete needs the last object incarnation).
 143   If it is not referenced on an existing serial (serial cleanup should be
 144   done _before_ history cleanup) then it can be deleted.
 145 
 146 
 147   SELECT FROM history LEFT JOIN serials WHERE timestamp<=?
 148     if record has serial_id NULL then delete it from history.
 149 */
 150 void cleanup_history() {
     /* [<][>][^][v][top][bottom][index][help] */
 151   SQ_result_set_t* rs;
 152   SQ_row_t*        row;
 153   char             query[300];
 154   char             delete_query[300];
 155   long             object_id;
 156   long             sequence_id;
 157 
 158   sprintf(query,
 159           "SELECT history.object_id, history.sequence_id, serials.serial_id "
 160           "  FROM history LEFT JOIN serials USING(object_id, sequence_id) "
 161           " WHERE history.timestamp<=%ld",
 162           end_time);
 163   SQ_execute_query(RIPE_conn, query, &rs);
 164   //printf("%s Q: %s\n", SQ_error(RIPE_conn), query);
 165   while ((row = SQ_row_next(rs)) != NULL) {
 166     //printf(".\n");
 167     if (SQ_get_column_string_nocopy(rs, row, 2) == NULL) {
 168       SQ_get_column_int(rs, row, 0, &object_id);
 169       SQ_get_column_int(rs, row, 1, &sequence_id);
 170       sprintf(delete_query,
 171               "DELETE "
 172               "  FROM history"
 173               " WHERE object_id = %ld AND sequence_id = %ld",
 174               object_id, sequence_id);
 175       //printf("DH: %s\n", delete_query);
 176       SQ_execute_query(RIPE_conn, delete_query, NULL);
 177     }
 178   }
 179 
 180   SQ_free_result(rs);
 181 }
 182 
 183 /*
 184   delete_last: deletes empty objects from last which are older than desired
 185 */
 186 void delete_last() {
     /* [<][>][^][v][top][bottom][index][help] */
 187   char delete_last[200];
 188   sprintf(delete_last,
 189           "DELETE FROM last WHERE timestamp<=%ld AND object=''",
 190           end_time);
 191   SQ_execute_query(RIPE_conn, delete_last, NULL);
 192 }
 193 
 194 /*
 195   set_end_timestamp: get max timestamp from archive to use it as limit.
 196 */
 197 void set_end_timestamp() {
     /* [<][>][^][v][top][bottom][index][help] */
 198   SQ_result_set_t* rs;
 199   SQ_row_t*        row;
 200 
 201   if (SQ_execute_query(archive_conn,
 202                        "SELECT max(timestamp) FROM archive",
 203                        &rs) != 0 ) {
 204     printf("Could not determine maximum timestamp on archive\n");
 205     exit(1);
 206   }
 207 
 208   row = SQ_row_next(rs);
 209 
 210   if (row == NULL) {
 211     printf("Could not determine maximum timestamp on archive\n");
 212     exit(1);
 213   }
 214 
 215   if (SQ_get_column_int(rs, row, 0, &end_time) != 0) {
 216     printf("Could not determine maximum timestamp on archive\n");
 217     exit(1);
 218   }
 219 
 220   //hard-coded less 1 week
 221   end_time = end_time - 60*60*24*7;
 222 }
 223 
 224 /*
 225   main: cleanup entry point
 226 
 227   self-documenting (see pseudo-code on iii).
 228 
 229   get_max_serial prepares variables to be used by delete_serials.
 230 */
 231 int main (int argv, char** argc) {
     /* [<][>][^][v][top][bottom][index][help] */
 232   process_arguments(argv, argc);
 233   read_configuration();
 234   get_db_connections();
 235 
 236   printf("Beginning cleanup");
 237   //printf("locking tables\n");
 238   if (SQ_execute_query(RIPE_conn,
 239                        "LOCK TABLES history WRITE, serials WRITE, "
 240                        "            last WRITE ", NULL) != 0) {
 241     printf("Could not lock tables for writing:\n%s\n", SQ_error(RIPE_conn));
 242     return 1;
 243   }
 244   //printf("tables locked\n");
 245 
 246   set_end_timestamp();
 247   //printf("ets: %ld\n", end_time);
 248   //printf("get_max_serial\n");
 249   get_max_serial();
 250   //printf("delete serials\n");
 251   delete_serials();
 252   //printf("cleanup history\n");
 253   cleanup_history();
 254   //printf("cleanup last\n");
 255   delete_last();
 256 
 257   SQ_execute_query(RIPE_conn, "UNLOCK TABLES", NULL);
 258   //close_dbs();
 259   printf("Ending sucessful cleanup");
 260   return 0;
 261 }
 262 

/* [<][>][^][v][top][bottom][index][help] */