]> andersk Git - moira.git/blob - dbck/dbck.pc
cef40d74a610b298d01529323f5b45de9fb82dcc
[moira.git] / dbck / dbck.pc
1 /* $Id$
2  *
3  * Moira database consistency checker
4  *
5  * (c) Copyright 1988-1998 by the Massachusetts Institute of Technology.
6  * For copying and distribution information, please see the file
7  * <mit-copyright.h>.
8  */
9
10 #include <mit-copyright.h>
11 #include <moira.h>
12 #include "dbck.h"
13
14 #include <signal.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17
18 EXEC SQL INCLUDE sqlca;
19 EXEC SQL INCLUDE sqlda;
20
21 RCSID("$Header$");
22
23 int debug = 0;
24 int mode = MODE_ASK;
25 int fast = 0;
26 int warn = 1;
27 int abort_p = 0;
28 struct hash *users, *machines, *clusters, *lists, *filesys, *nfsphys;
29 struct hash *strings, *members, *subnets, *string_dups;
30 EXEC SQL BEGIN DECLARE SECTION;
31 int dcmenable;
32 EXEC SQL END DECLARE SECTION;
33 struct save_queue *modtables;
34 SQLDA *mr_sqlda;
35
36 void interrupt(void);
37 extern SQLDA *sqlald(int, int, int);
38 extern void sqlglm(char *, unsigned int *, unsigned int *);
39
40 int main(int argc, char **argv)
41 {
42   char **arg = argv;
43   EXEC SQL BEGIN DECLARE SECTION;
44   char *database;
45   EXEC SQL END DECLARE SECTION;
46   int countonly = 0;
47   struct sigaction sa;
48
49   database = "moira";
50   setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
51
52   while (++arg - argv < argc)
53     {
54       if  (**arg == '-')
55         {
56           switch ((*arg)[1])
57             {
58             case 'd':
59               debug = atoi((*arg)[2] ? *arg + 2 : *++arg);
60               break;
61             case 'n':
62               mode = MODE_NO;
63               break;
64             case 'y':
65               mode = MODE_YES;
66               break;
67             case 'p':
68               mode = MODE_PREEN;
69               break;
70             case 'a':
71               mode = MODE_ASK;
72               break;
73             case 'c':
74               countonly++;
75               break;
76             case 'f':
77               fast++;
78               break;
79             case 'w':
80               warn = 0;
81               break;
82             default:
83               printf("Usage: %s [-d level] [-n] [-y] [-p] [-a] [-c] [-f] [-w] [database]\n",
84                      argv[0]);
85               exit(1);
86             }
87         }
88       else
89         database = *arg;
90     }
91   if (countonly)
92     printf("Only doing counts\n");
93   else if (fast)
94     printf("Doing fast version (skipping some checks)\n");
95   if (mode == MODE_NO)
96     printf("Will NOT modify the database\n");
97   else if (mode == MODE_PREEN)
98     printf("Will fix simple things without asking\n");
99   else if (mode == MODE_YES)
100     printf("Will fix everything without asking\n");
101   if (debug)
102     printf("Debug level is %d\n", debug);
103
104   sa.sa_handler = interrupt;
105   sa.sa_flags = 0;
106   sigemptyset(&sa.sa_mask);
107   sigaction(SIGHUP, &sa, NULL);
108   sigaction(SIGQUIT, &sa, NULL);
109   sigaction(SIGINT, &sa, NULL);
110
111   modtables = sq_create();
112   mr_sqlda = sqlald(1, 255, 0);
113
114   EXEC SQL WHENEVER SQLERROR DO dbmserr();
115   printf("Opening database %s...", database);
116   fflush(stdout);
117   EXEC SQL CONNECT :database IDENTIFIED BY :database;
118   printf("done\n");
119   EXEC SQL SELECT value INTO :dcmenable FROM numvalues
120     WHERE name = 'dcm_enable';
121   dprintf("DCM disabled (was %d)\n", dcmenable);
122   EXEC SQL UPDATE numvalues SET value = 0 WHERE name = 'dcm_enable';
123
124   /* Begin transaction here. */
125
126   if (!countonly)
127     {
128       phase1();
129       EXEC SQL COMMIT WORK;
130       phase2();
131       EXEC SQL COMMIT WORK;
132       phase3();
133       EXEC SQL COMMIT WORK;
134     }
135   else
136     {
137       count_only_setup();
138       EXEC SQL COMMIT WORK;
139     }
140   phase4();
141   EXEC SQL COMMIT WORK;
142
143   cleanup();
144   printf("Done.\n");
145   exit(0);
146 }
147
148 void dbmserr(void)
149 {
150   EXEC SQL BEGIN DECLARE SECTION;
151   char buf[512];
152   EXEC SQL END DECLARE SECTION;
153   int bufsize = 256, msglength = 0;
154
155   if (sqlca.sqlcode == 1403)
156     return;
157   printf("A DBMS error occurred, code %ld\n", sqlca.sqlcode);
158   sqlglm(buf, &bufsize, &msglength);
159   buf[msglength] = '\0';
160   printf("%s\n", buf);
161   printf("Aborting...\n");
162   if (!abort_p)
163     {
164       abort_p++;
165       EXEC SQL ROLLBACK WORK;
166     }
167   exit(1);
168 }
169
170
171 void interrupt(void)
172 {
173   printf("Signal caught\n");
174   if (prompt("Save database changes"))
175     {
176       EXEC SQL COMMIT WORK;
177       cleanup();
178       exit(0);
179     }
180   printf("Aborting transaction\n");
181   if (!abort_p)
182     {
183       abort_p++;
184       EXEC SQL ROLLBACK WORK;
185     }
186
187   EXEC SQL UPDATE numvalues SET value = :dcmenable
188     WHERE name = 'dcm_enable';
189
190   exit(0);
191 }
192
193
194 void modified(char *table)
195 {
196   sq_save_unique_string(modtables, table);
197 }
198
199 void cleanup(void)
200 {
201   EXEC SQL BEGIN DECLARE SECTION;
202   char *tab;
203   EXEC SQL END DECLARE SECTION;
204
205   while (sq_get_data(modtables, &tab))
206     {
207       EXEC SQL UPDATE tblstats SET modtime = SYSDATE
208         WHERE table_name = :tab;
209     }
210   EXEC SQL UPDATE numvalues SET value = :dcmenable
211     WHERE name = 'dcm_enable';
212 }
213
214
215 void out_of_mem(char *msg)
216 {
217   fprintf(stderr, "Out of memory while %s\n", msg);
218   if (prompt("Save database changes"))
219     {
220       EXEC SQL COMMIT WORK;
221       cleanup();
222       exit(1);
223     }
224   printf("Aborting transaction\n");
225   EXEC SQL ROLLBACK WORK;
226   exit(1);
227 }
This page took 0.044587 seconds and 3 git commands to generate.