view db.c @ 7:9a14029b3782

- Wait longer (100msec) for a read, and reduce the number of retries to match. - Print out if we read OK after more than 1 attempt for diagnostic purposes.
author Daniel O'Connor <darius@dons.net.au>
date Thu, 11 Feb 2010 12:47:59 +1030
parents e0b32014ed14
children
line wrap: on
line source

/*
 * Report weather conditions to remote web sites.
 * Database access and startup functions.
 *
 * Greg Lehey, 14 December 2009
 *
 * $Id: db.c,v 1.5 2010/02/04 03:50:35 grog Exp $
 */

#include <stdlib.h>

#include "wh1080.h"

#define STAMPSIZE 32                            /* size of time stamp to print out */

/* Command line options */
int debug;                                      /* -d */
int update = 1;                                 /* -n turns updating off  */
int recover = 0;                                /* -r: recover missed archive data (wh1080 only) */
int verbose;                                    /* -v */
int once;                                       /* -1 */

struct passwd *mypasswd;                        /* password information for default user */

/* MySQL stuff */
MYSQL *mysql;
MYSQL_RES *mysql_result;
MYSQL_ROW mysql_row;
char mysql_querytext [1024];                    /* build up queries here */
struct config config;

void db_login ()
{
  if (! mysql_init (mysql))
  {
    fprintf (stderr, "Can't initialize MySQL\n");
    exit (1);
  }
  mysql = mysql_init (mysql);
  if (! mysql)
  {
    fprintf (stderr, "Can't initialize MySQL: insufficient memory\n");
    exit (1);
  }
  if (! mysql_real_connect (mysql,              /* DB state */
                            config.db_host,     /* database host */
                            config.db_user,
                            config.db_passwd,
                            config.db,
                            0,
                            NULL,
                            0 ))
  {
    fprintf (stderr,
             "Can't connect to databaase: %s (%d)\n",
             mysql_error (mysql),
             mysql_errno (mysql) );
    exit (1);
  }
}

/*
 * Perform a database query, return result to myresult.
 */
int domyquery (char *query, MYSQL_RES **myresult)
{
  if (mysql_query (mysql, query))
  {
    fprintf (stderr,
             "Can't query database: %s (%d)\n"
             "  query:%s\n",
             mysql_error (mysql),
             mysql_errno (mysql),
             query );
    return 1;
  }
  *myresult = mysql_store_result (mysql);
  return 0;
}

/*
 * Perform a database query, return result to implicit mysql_result.
 */
int doquery (char *query)
{
  return domyquery (query, &mysql_result);
}

/*
 * Make a copy of a string in malloced memory and return it.
 */
char *mycopy (char *string)
{
  char *result = malloc (strlen (string) + 1);
  strcpy (result, string);
  return result;
}

/*
 * Read in config from database.
 *
 * XXX We have a chicken and egg problem here: the config information includes
 * the database name, but we need to know that before we start.  For the time
 * being we supply necessary information on the command line, with defaults.
 * FIXME.
 */
int read_config (int argc, char *argv [])
{
  int col;
  int arg;

  for (arg = 1; arg < argc; arg++)
  {
    if (! strcmp (argv [arg], "-d"))
      debug = 1;
    else if (! strcmp (argv [arg], "-n"))       /* turn off DB updates */
      update = 0;
    else if (! strcmp (argv [arg], "-v"))       /* verbose */
      verbose = 1;
    else if (! strcmp (argv [arg], "-vv"))       /* more verbose */
      verbose = 2;
    else if (! strcmp (argv [arg], "-1"))       /* run once and exit */
      once = 1;
    else
    {
      if (! config.station_id)
        config.station_id = argv [arg];
      else if (! config.db_user)
        config.db_user = argv [arg];
      else if (! config.db_passwd)
        config.db_passwd = argv [arg];
      else if (! config.db_host)
        config.db_host = argv [arg];
      else if (! config.db)
        config.db = argv [arg];
      else
      {
        fprintf (stderr, "Too many arguments: %s\n", argv [arg]);
        return -1;
      }
    }
  }

  /* Set default values for config stuff above. */
  if (! config.station_id)
    config.station_id = "mystation";
  if (! config.db_host)
    config.db_host = "localhost";
  if (! config.db_user)
  {
    /* Find out user name and use it */
    mypasswd = getpwuid (getuid ());
    if (mypasswd)
      config.db_user = mycopy (mypasswd->pw_name);
    else
    {
      fprintf (stderr, "Can't get default user id\n");
      exit (1);
    }
  }
  if (! config.db_passwd)
    config.db_passwd = "";
  if (! config.db)
    config.db = "weather";

  /* No updates required so don't bother with DB stuff */
  if (!update) {
    config.poll_interval = 60;
    return 0;
  }
  
  if (! mysql_init (mysql))
  {
    fprintf (stderr, "Can't initialize MySQL\n");
    exit (1);
  }
  mysql = mysql_init (mysql);
  if (! mysql)
  {
    fprintf (stderr, "Can't initialize MySQL: insufficient memory\n");
    exit (1);
  }
  if (! mysql_real_connect (mysql,              /* DB state */
			    config.db_host,     /* database host */
			    config.db_user,
			    config.db_passwd,
			    config.db,
			    0,
			    NULL,
			    0 ))
  {
    fprintf (stderr,
	     "Can't connect to databaase: %s (%d)\n",
	     mysql_error (mysql),
	     mysql_errno (mysql) );
    exit (1);
  }

  /*
   * Read the rest of the config from specified database.
   */

  sprintf (mysql_querytext,
	   "SELECT version,\n"
	   "       latitude,\n"
	   "       longitude,\n"
	   "       elevation,\n"
	   "       pressure_error,\n"
	   "       poll_interval,\n"
	   "       address,\n"
	   "       wunderground_station_id,\n"
	   "       wunderground_passwd,\n"
	   "       wunderground_report_interval,\n"
	   "       weatheforyou_station_id,\n"
	   "       weatheforyou_passwd,\n"
	   "       weatherforyou_report_interval,\n"
	   "       website_generation_interval,\n"
	   "       db_table,\n"
	   "       php_header,\n"
	   "       comparefile\n"
	   "FROM config\n"
	   "WHERE station_id = \"%s\";\n",
	   config.station_id );
  if (doquery (mysql_querytext))                /* failure */
    exit (1);

  if (! (mysql_row = mysql_fetch_row (mysql_result))) /* got something */
  {
    fprintf (stderr, "No configuration file found\n");
    exit (1);
  }

  /*
   * XXX here we should perform a version check.  Do it when we introduce
   * version 2.
   */
  /* And this is filthy ugly.  Fix it */
  col = 1;
  config.latitude = atof (mysql_row [col++]);
  config.longitude = atof (mysql_row [col++]);
  config.elevation = atof (mysql_row [col++]);  /* metres */
  config.pressure_error = atof (mysql_row [col++]); /* difference between actual and real pressure, hPa */
  config.poll_interval = atoi (mysql_row [col++]); /* time, in seconds, between reading the device */
  config.address = mycopy (mysql_row [col++]);  /* Address to display on web pages */
  config.wunderground_station_id = mycopy (mysql_row [col++]);
  config.wunderground_passwd = mycopy (mysql_row [col++]);
  config.wunderground_report_interval = atoi (mysql_row [col++]); /* how many seconds between reports to Wunderground */
  config.weatheforyou_station_id = mycopy (mysql_row [col++]);
  config.weatheforyou_passwd = mycopy (mysql_row [col++]);
  config.weatherforyou_report_interval = atoi (mysql_row [col++]); /* how many seconds between reports to Weather for you */
  config.website_generation_interval = atoi (mysql_row [col++]); /* how many seconds between generating PHP header file */
  config.db_table = mycopy (mysql_row [col++]); /* table */
  config.php_header = mycopy (mysql_row [col++]); /* php header file with weather data */
  config.comparefile = mycopy (mysql_row [col++]); /* file to compare local weather stations */
  
  return 0;                                     /* success */
}