## 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] */