utils/text_export/text_export.c

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

FUNCTIONS

This source file includes following functions.
  1. dump_putc
  2. dump_fputs
  3. get_program_name
  4. syntax
  5. parse_options
  6. load_classes
  7. output_object
  8. seperate_time_t
  9. main

   1 /* text_export - output RIP database into text files of RPSL objects */
   2 
   3 /*
   4 Copyright (c) 2000,2001,2002            RIPE NCC
   5 
   6 
   7 All Rights Reserved
   8 
   9 Permission to use, copy, modify, and distribute this software and its
  10 documentation for any purpose and without fee is hereby granted,
  11 provided that the above copyright notice appear in all copies and that
  12 both that copyright notice and this permission notice appear in
  13 supporting documentation, and that the name of the author not be
  14 used in advertising or publicity pertaining to distribution of the
  15 software without specific, written prior permission.
  16 
  17 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  18 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  19 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  20 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  21 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  22 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  23 */
  24 
  25 /* $Id: text_export.c,v 1.4 2002/02/19 17:22:47 shane Exp $ */
  26 
  27 #include <stdio.h>
  28 #include <unistd.h>
  29 #include <stdlib.h>
  30 #include <string.h>
  31 #include <ctype.h>
  32 #include <time.h>
  33 #include <assert.h>
  34 
  35 #include "mysql_driver.h"
  36 #include "defs.h"
  37 #include "memwrap.h"
  38 #include "query_instructions.h"
  39 
  40 /* global variables */
  41 char *Program_Name;
  42 int Verbose = 0;
  43 long long Amt_Dumped = 0;
  44 
  45 /* structure holding information used to connect to SQL server */
  46 struct database_info {
  47     char *hostname;
  48     int port;
  49     char *database;
  50     char *user;
  51     char *password;
  52 };
  53 
  54 /* structure for class */
  55 struct class {
  56     char *name;
  57     FILE *fp;
  58     char *short_name;
  59     FILE *short_fp;
  60 };
  61 
  62 /* output functions which track amount of data written */
  63 #define dump_putc(c,stream)  (Amt_Dumped++, putc((c),(stream)))
     /* [<][>][^][v][top][bottom][index][help] */
  64 void dump_fputs(const char *s, FILE *stream)
     /* [<][>][^][v][top][bottom][index][help] */
  65 {
  66     Amt_Dumped += fputs(s, stream);
  67 }
  68 
  69 /* extracts the program name from command-line arguments */
  70 void get_program_name(int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
  71 {
  72     char *p;
  73 
  74     if (argc <= 0) {
  75         fprintf(stderr, "ERROR: unable to determine program name\n");
  76         exit(1);
  77     }
  78 
  79     p = strrchr(argv[0], '/');
  80     if (p == NULL) {
  81         Program_Name = argv[0];
  82     } else {
  83         Program_Name = p+1;
  84     }
  85 }
  86 
  87 void syntax()
     /* [<][>][^][v][top][bottom][index][help] */
  88 {
  89     fprintf(stderr, 
  90         "Syntax: %s [-v] [-h hostname] [-P port] [-u user] [-p password] "
  91         "database\n", Program_Name);
  92 }
  93 
  94 /* exits on error */
  95 void parse_options(int argc, char **argv, struct database_info *db)
     /* [<][>][^][v][top][bottom][index][help] */
  96 {
  97     int opt;
  98 
  99     /* defaults */
 100     db->hostname = "localhost";
 101     db->port = 0;
 102     db->user = "";
 103     db->password = "";
 104 
 105     /* parse command line arguments with the ever-handy getopt() */
 106     while ((opt = getopt(argc, argv, "vh:u:p:P:")) != -1) {
 107         switch (opt) {
 108             case 'v': 
 109                 Verbose++;
 110                 break;
 111             case 'h': 
 112                 db->hostname = optarg;
 113                 break;
 114             case 'P': 
 115                 db->port = atoi(optarg);
 116                 break;
 117             case 'u': 
 118                 db->user = optarg;
 119                 break;
 120             case 'p':
 121                 db->password = optarg;
 122                 break;
 123             case '?':
 124                 syntax();
 125                 exit(1);
 126         }
 127     }
 128 
 129     /* check remaining argument count */
 130     argc -= optind;
 131     argv += optind;
 132     if (argc != 1) {
 133         syntax();
 134         exit(1);
 135     }
 136 
 137     /* remaining argument should be database name */
 138     db->database = argv[0];
 139 }
 140 
 141 int load_classes(struct class **c) 
     /* [<][>][^][v][top][bottom][index][help] */
 142 {
 143     char* const *class_names;
 144     int num_classes;
 145     struct class *tmp;
 146     int i;
 147     char fname[64];
 148 
 149     class_names = DF_get_class_names();
 150     num_classes = 0;
 151     while (class_names[num_classes] != NULL) {
 152         num_classes++;
 153     }
 154     wr_malloc((void *)&tmp, sizeof(struct class) * num_classes);
 155 
 156     for (i=0; i<num_classes; i++) {
 157         tmp[i].name = class_names[i];
 158         tmp[i].short_name = 
 159             DF_get_class_code(DF_class_name2type(class_names[i]));
 160 
 161         assert(strlen(tmp[i].name) < 60);
 162         strcpy(fname, "db.");
 163         strcat(fname, tmp[i].name);
 164         tmp[i].fp = fopen(fname, "w+");
 165         if (tmp[i].fp == NULL) {
 166             fprintf(stderr, "%s: error opening file \"%s\"\n", 
 167                 Program_Name, fname);
 168             exit(1);
 169         }
 170 
 171         assert(strlen(tmp[i].short_name) < 60);
 172         strcpy(fname, "db.");
 173         strcat(fname, tmp[i].short_name);
 174         tmp[i].short_fp = fopen(fname, "w+");
 175         if (tmp[i].short_fp == NULL) {
 176             fprintf(stderr, "%s: error opening file \"%s\"\n", 
 177                 Program_Name, fname);
 178             exit(1);
 179         }
 180     }
 181 
 182     *c = tmp;
 183     return num_classes;
 184 }
 185 
 186 /* outputs the object to the appropriate files */
 187 void output_object(char *object, struct class *c, int num_classes)
     /* [<][>][^][v][top][bottom][index][help] */
 188 {
 189     char *p;
 190     int i;
 191 
 192     p = strchr(object, ':');
 193     if (p == NULL) {
 194         fprintf(stderr, 
 195             "%s: format error in database; no colon in object, \"%s\"\n",
 196             Program_Name, object);
 197         exit(1);
 198     }
 199     *p = '\0';
 200 
 201     for (i=0; i<num_classes; i++) {
 202         if (strcmp(c[i].name, object) == 0) {
 203             *p = ':';
 204             dump_fputs(object, c[i].fp);
 205             dump_putc('\n', c[i].fp);
 206             p = QI_fast_output(object);
 207             dump_fputs(p, c[i].short_fp);
 208             free(p);
 209             dump_putc('\n', c[i].short_fp);
 210             return;
 211         }
 212     }
 213 
 214     fprintf(stderr, "%s: unknown class of object found, \"%s\"\n",
 215         Program_Name, object);
 216     exit(1);
 217 }
 218 
 219 void seperate_time_t(int n, int *hours, int *minutes, int *seconds)
     /* [<][>][^][v][top][bottom][index][help] */
 220 {
 221     *hours = n / (60 * 60);
 222     n %= (60 * 60);
 223     *minutes = n / 60;
 224     n %= 60;
 225     *seconds = n;
 226 }
 227 
 228 /* program entry point */
 229 int main(int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 230 {
 231     struct database_info db;
 232     er_ret_t ret;
 233     SQ_connection_t *sql;
 234     int num_classes;
 235     struct class *classes;
 236     SQ_result_set_t *rs;
 237     SQ_row_t *row;
 238     int num_object;
 239     time_t start, end;
 240     const struct tm *now;
 241     char tmp[64];
 242     double runtime;
 243     int h, m, s;
 244 
 245     /* turn off output buffering (why isn't this the default?) */
 246     setbuf(stdout, NULL);
 247 
 248     /* record our program's name for any future use */
 249     get_program_name(argc, argv);
 250 
 251     /* parse our command line */
 252     parse_options(argc, argv, &db);
 253     if (Verbose) {
 254         printf("\n");
 255         printf("Command line options\n");
 256         printf("  database: %s\n", db.database);
 257         printf("  hostname: %s\n", db.hostname);
 258         if (db.port) {
 259             printf("      port: %d\n", db.port);
 260         } else {
 261             printf("      port: <default>\n");
 262         }
 263         printf("      user: %s\n", (*db.user == '\0') ? "<default>" : db.user);
 264         printf("  password: <hidden>\n");
 265     }
 266 
 267     /* connect to the server */
 268 
 269     if (Verbose) {
 270         printf("\n");
 271         printf("Connecting to server...\n");
 272     }
 273 
 274     ret = SQ_try_connection(&sql, 
 275         db.hostname, db.port, db.database, db.user, db.password);
 276     if (!NOERR(ret)) {
 277         fprintf(stderr, "%s: error connecting to database; %s\n", Program_Name,
 278             SQ_error(sql));
 279         exit(1);
 280     }
 281 
 282     if (Verbose) {
 283         printf("Connected.\n");
 284     }
 285 
 286 
 287     /* submit our query */
 288     if (Verbose) {
 289         printf("\n");
 290         printf("Submitting query...\n");
 291     }
 292 
 293     if (SQ_execute_query_nostore(sql, 
 294         "SELECT object FROM last "
 295         "WHERE (thread_id=0) AND (object_type<>100) AND (object<>\"\")", 
 296         &rs) != 0) 
 297     {
 298        fprintf(stderr, "%s: error with query; %s\n", Program_Name, 
 299            SQ_error(sql));
 300        exit(1);
 301     }
 302 
 303     if (Verbose) {
 304         printf("Submitted.\n");
 305     }
 306 
 307 
 308     /* initialize our class information (also creates output files) */
 309     num_classes = load_classes(&classes);
 310 
 311     /* record start time */
 312     time(&start);
 313 
 314     if (Verbose) {
 315         printf("\n");
 316         printf("Loaded %d classes\n", num_classes);
 317         printf("Created %d output files\n", num_classes * 2);
 318         printf("\n");
 319         now = localtime(&start);
 320         strftime(tmp, sizeof(tmp), "Dump starting... %Y-%m-%d %H:%M:%S %Z",
 321             now);
 322         puts(tmp);
 323     }
 324 
 325 
 326     /* read our MySQL data */
 327     num_object = 0;
 328     while ((row = SQ_row_next(rs)) != NULL) {
 329         char *object = SQ_get_column_string_nocopy(rs, row, 0);
 330         output_object(object, classes, num_classes);
 331         num_object++;
 332     }
 333 
 334     /* close up shop */
 335     time(&end);
 336 
 337     /* output final results, if any */
 338     if (Verbose) {
 339         now = localtime(&end);
 340         strftime(tmp, sizeof(tmp), "Dump finished... %Y-%m-%d %H:%M:%S %Z",
 341             now);
 342         puts(tmp);
 343         runtime = difftime(end, start);
 344         seperate_time_t((int)(runtime + 0.5), &h, &m, &s);
 345         printf("Wrote %d objects in %d:%02d:%02d\n", num_object, h, m, s);
 346         printf(" %12.2f objects/second\n", num_object/runtime);
 347         printf(" %12.2f byte/second\n", Amt_Dumped/runtime);
 348         printf("\n");
 349     }
 350 
 351     /* assume that 0 outputs is an error */
 352     if (num_object == 0) {
 353         fprintf(stderr, "No objects dumped, exiting with error\n");
 354         exit(1);
 355     }
 356 
 357     return 0;
 358 }
 359 

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