utils/text_export/text_export.c

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

DEFINITIONS

This source file includes following functions.
  1. dump_fputs
  2. get_program_name
  3. syntax
  4. parse_options
  5. load_classes
  6. output_object
  7. seperate_time_t
  8. 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.5 2002/04/16 11:53:00 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 int Dump_Short = 0;
  45 
  46 /* structure holding information used to connect to SQL server */
  47 struct database_info {
  48     char *hostname;
  49     int port;
  50     char *database;
  51     char *user;
  52     char *password;
  53 };
  54 
  55 /* structure for class */
  56 struct class {
  57     char *name;
  58     FILE *fp;
  59     char *short_name;
  60     FILE *short_fp;
  61 };
  62 
  63 /* output functions which track amount of data written */
  64 #define dump_putc(c,stream)  (Amt_Dumped++, putc((c),(stream)))
  65 void 
  66 dump_fputs (const char *s, FILE *stream)
     /* [<][>][^][v][top][bottom][index][help] */
  67 {
  68     Amt_Dumped += fputs(s, stream);
  69 }
  70 
  71 /* extracts the program name from command-line arguments */
  72 void 
  73 get_program_name (int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
  74 {
  75     char *p;
  76 
  77     if (argc <= 0) {
  78         fprintf(stderr, "ERROR: unable to determine program name\n");
  79         exit(1);
  80     }
  81 
  82     p = strrchr(argv[0], '/');
  83     if (p == NULL) {
  84         Program_Name = argv[0];
  85     } else {
  86         Program_Name = p+1;
  87     }
  88 }
  89 
  90 void 
  91 syntax ()
     /* [<][>][^][v][top][bottom][index][help] */
  92 {
  93     fprintf(stderr, 
  94         "Syntax: %s [-v] [-h hostname] [-P port] [-u user] [-p password] [-s]"
  95         "database\n", Program_Name);
  96 }
  97 
  98 /* exits on error */
  99 void 
 100 parse_options (int argc, char **argv, struct database_info *db, int *dump_short)
     /* [<][>][^][v][top][bottom][index][help] */
 101 {
 102     int opt;
 103 
 104     /* defaults */
 105     db->hostname = "localhost";
 106     db->port = 0;
 107     db->user = "";
 108     db->password = "";
 109     *dump_short = 0;
 110 
 111     /* parse command line arguments with the ever-handy getopt() */
 112     while ((opt = getopt(argc, argv, "vh:u:p:P:s")) != -1) {
 113         switch (opt) {
 114             case 'v': 
 115                 Verbose++;
 116                 break;
 117             case 'h': 
 118                 db->hostname = optarg;
 119                 break;
 120             case 'P': 
 121                 db->port = atoi(optarg);
 122                 break;
 123             case 'u': 
 124                 db->user = optarg;
 125                 break;
 126             case 'p':
 127                 db->password = optarg;
 128                 break;
 129             case 's':
 130                 *dump_short = 1;
 131                 break;
 132             case '?':
 133                 syntax();
 134                 exit(1);
 135         }
 136     }
 137 
 138     /* check remaining argument count */
 139     argc -= optind;
 140     argv += optind;
 141     if (argc != 1) {
 142         syntax();
 143         exit(1);
 144     }
 145 
 146     /* remaining argument should be database name */
 147     db->database = argv[0];
 148 }
 149 
 150 int 
 151 load_classes (struct class **c) 
     /* [<][>][^][v][top][bottom][index][help] */
 152 {
 153     char* const *class_names;
 154     int num_classes;
 155     struct class *tmp;
 156     int i;
 157     char fname[64];
 158 
 159     class_names = DF_get_class_names();
 160     num_classes = 0;
 161     while (class_names[num_classes] != NULL) {
 162         num_classes++;
 163     }
 164     wr_malloc((void *)&tmp, sizeof(struct class) * num_classes);
 165 
 166     for (i=0; i<num_classes; i++) {
 167         tmp[i].name = class_names[i];
 168 
 169         assert(strlen(tmp[i].name) < 60);
 170         strcpy(fname, "db.");
 171         strcat(fname, tmp[i].name);
 172         tmp[i].fp = fopen(fname, "w+");
 173         if (tmp[i].fp == NULL) {
 174             fprintf(stderr, "%s: error opening file \"%s\"\n", 
 175                 Program_Name, fname);
 176             exit(1);
 177         }
 178 
 179         if (Dump_Short) {
 180             tmp[i].short_name = 
 181                 DF_get_class_code(DF_class_name2type(class_names[i]));
 182             assert(strlen(tmp[i].short_name) < 60);
 183             strcpy(fname, "db.");
 184             strcat(fname, tmp[i].short_name);
 185             tmp[i].short_fp = fopen(fname, "w+");
 186             if (tmp[i].short_fp == NULL) {
 187                 fprintf(stderr, "%s: error opening file \"%s\"\n", 
 188                     Program_Name, fname);
 189                 exit(1);
 190             }
 191         } else {
 192             tmp[i].short_name = NULL;
 193             tmp[i].short_fp = NULL;
 194         }
 195     }
 196 
 197     *c = tmp;
 198     return num_classes;
 199 }
 200 
 201 /* outputs the object to the appropriate files */
 202 void 
 203 output_object (char *object, struct class *c, int num_classes)
     /* [<][>][^][v][top][bottom][index][help] */
 204 {
 205     char *p;
 206     int i;
 207 
 208     p = strchr(object, ':');
 209     if (p == NULL) {
 210         fprintf(stderr, 
 211             "%s: format error in database; no colon in object, \"%s\"\n",
 212             Program_Name, object);
 213         exit(1);
 214     }
 215     *p = '\0';
 216 
 217     for (i=0; i<num_classes; i++) {
 218         if (strcmp(c[i].name, object) == 0) {
 219             *p = ':';
 220             dump_fputs(object, c[i].fp);
 221             dump_putc('\n', c[i].fp);
 222             if (Dump_Short) {
 223                 p = QI_fast_output(object);
 224                 dump_fputs(p, c[i].short_fp);
 225                 free(p);
 226                 dump_putc('\n', c[i].short_fp);
 227             }
 228             return;
 229         }
 230     }
 231 
 232     fprintf(stderr, "%s: unknown class of object found, \"%s\"\n",
 233         Program_Name, object);
 234     exit(1);
 235 }
 236 
 237 void 
 238 seperate_time_t (int n, int *hours, int *minutes, int *seconds)
     /* [<][>][^][v][top][bottom][index][help] */
 239 {
 240     *hours = n / (60 * 60);
 241     n %= (60 * 60);
 242     *minutes = n / 60;
 243     n %= 60;
 244     *seconds = n;
 245 }
 246 
 247 /* program entry point */
 248 int 
 249 main (int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 250 {
 251     struct database_info db;
 252     er_ret_t ret;
 253     SQ_connection_t *sql;
 254     int num_classes;
 255     struct class *classes;
 256     SQ_result_set_t *rs;
 257     SQ_row_t *row;
 258     int num_object;
 259     time_t start, end;
 260     const struct tm *now;
 261     char tmp[64];
 262     double runtime;
 263     int h, m, s;
 264 
 265     /* turn off output buffering (why isn't this the default?) */
 266     setbuf(stdout, NULL);
 267 
 268     /* record our program's name for any future use */
 269     get_program_name(argc, argv);
 270 
 271     /* parse our command line */
 272     parse_options(argc, argv, &db, &Dump_Short);
 273     if (Verbose) {
 274         printf("\n");
 275         printf("Command line options\n");
 276         printf("   database: %s\n", db.database);
 277         printf("   hostname: %s\n", db.hostname);
 278         if (db.port) {
 279             printf("       port: %d\n", db.port);
 280         } else {
 281             printf("       port: <default>\n");
 282         }
 283         printf("       user: %s\n", (*db.user == '\0') ? "<default>" : db.user);
 284         printf("   password: <hidden>\n");
 285         printf(" dump short: %s\n", Dump_Short ? "yes" : "no");
 286     }
 287 
 288     /* connect to the server */
 289 
 290     if (Verbose) {
 291         printf("\n");
 292         printf("Connecting to server...\n");
 293     }
 294 
 295     ret = SQ_try_connection(&sql, 
 296         db.hostname, db.port, db.database, db.user, db.password);
 297     if (!NOERR(ret)) {
 298         fprintf(stderr, "%s: error connecting to database; %s\n", Program_Name,
 299             SQ_error(sql));
 300         exit(1);
 301     }
 302 
 303     if (Verbose) {
 304         printf("Connected.\n");
 305     }
 306 
 307 
 308     /* submit our query */
 309     if (Verbose) {
 310         printf("\n");
 311         printf("Submitting query...\n");
 312     }
 313 
 314     if (SQ_execute_query_nostore(sql, 
 315         "SELECT object FROM last "
 316         "WHERE (thread_id=0) AND (object_type<>100) AND (object<>\"\")", 
 317         &rs) != 0) 
 318     {
 319        fprintf(stderr, "%s: error with query; %s\n", Program_Name, 
 320            SQ_error(sql));
 321        exit(1);
 322     }
 323 
 324     if (Verbose) {
 325         printf("Submitted.\n");
 326     }
 327 
 328 
 329     /* initialize our class information (also creates output files) */
 330     num_classes = load_classes(&classes);
 331 
 332     /* record start time */
 333     time(&start);
 334 
 335     if (Verbose) {
 336         printf("\n");
 337         printf("Loaded %d classes\n", num_classes);
 338         printf("Created %d output files\n", 
 339             Dump_Short ? (num_classes * 2) : num_classes);
 340         printf("\n");
 341         now = localtime(&start);
 342         strftime(tmp, sizeof(tmp), "Dump starting... %Y-%m-%d %H:%M:%S %Z",
 343             now);
 344         puts(tmp);
 345     }
 346 
 347 
 348     /* read our MySQL data */
 349     num_object = 0;
 350     while ((row = SQ_row_next(rs)) != NULL) {
 351         char *object = SQ_get_column_string_nocopy(rs, row, 0);
 352         output_object(object, classes, num_classes);
 353         num_object++;
 354     }
 355 
 356     /* close up shop */
 357     time(&end);
 358 
 359     /* output final results, if any */
 360     if (Verbose) {
 361         now = localtime(&end);
 362         strftime(tmp, sizeof(tmp), "Dump finished... %Y-%m-%d %H:%M:%S %Z",
 363             now);
 364         puts(tmp);
 365         runtime = difftime(end, start);
 366         seperate_time_t((int)(runtime + 0.5), &h, &m, &s);
 367         printf("Wrote %d objects in %d:%02d:%02d\n", num_object, h, m, s);
 368         printf(" %12.2f objects/second\n", num_object/runtime);
 369         printf(" %12.2f byte/second\n", Amt_Dumped/runtime);
 370         printf("\n");
 371     }
 372 
 373     /* assume that 0 outputs is an error */
 374     if (num_object == 0) {
 375         fprintf(stderr, "No objects dumped, exiting with error\n");
 376         exit(1);
 377     }
 378 
 379     return 0;
 380 }
 381 

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