/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following functions.
- process_arguments
- get_max_serial
- delete_serials
- cleanup_history
- delete_last
- set_end_timestamp
- 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