Example #1
0
static void report_stats(void)
{
   char zs[128];
   word i;
   char report[2048];

   _log(GENERAL, "");
   sprintf(zs, "%25s: %-12s Total", "", "Day");
   _log(GENERAL, zs);
   strcpy(report, zs);
   strcat(report, "\n");

   sprintf(zs, "%25s: %-12s %ld days", "Run time", "", (time(NULL)-start_time)/(24*60*60));
   _log(GENERAL, zs);
   strcat(report, zs);
   strcat(report, "\n");
   for(i=0; i<MAXstats; i++)
   {
      grand_stats[i] += stats[i];
      sprintf(zs, "%25s: %-12s ", stats_category[i], commas_q(stats[i]));
      strcat(zs, commas_q(grand_stats[i]));
      _log(GENERAL, zs);
      strcat(report, zs);
      strcat(report, "\n");
      stats[i] = 0;
   }
   email_alert(NAME, BUILD, "Statistics Report", report);
}
Example #2
0
static void process_create_schedule(const char * string, const jsmntok_t * tokens, const word update)
{
   // update true indicates this is as the result of a VSTP update.
   char zs[128], zs1[128];
   char query[2048];
   word i;
   char uid[16], stp_indicator[2];
   char signalling_id[8];

   if(debug) jsmn_dump_tokens(string, tokens, 0);

   time_t now = time(NULL);
   sprintf(query, "INSERT INTO cif_schedules VALUES(0, %ld, %lu", now, NOT_DELETED); // update_id == 0 => VSTP

   EXTRACT_APPEND_SQL("CIF_bank_holiday_running");

   //EXTRACT_APPEND_SQL("CIF_stp_indicator");
   EXTRACT("CIF_stp_indicator", stp_indicator);
   sprintf(zs1, ", '%s'", stp_indicator); strcat(query, zs1); 

   //EXTRACT_APPEND_SQL("CIF_train_uid");
   EXTRACT("CIF_train_uid", uid);
   sprintf(zs1, ", '%s'", uid); strcat(query, zs1); 

   EXTRACT_APPEND_SQL("applicable_timetable");

   EXTRACT_APPEND_SQL("atoc_code");
   // EXTRACT_APPEND_SQL("traction_class");
   EXTRACT_APPEND_SQL("uic_code");
   EXTRACT("schedule_days_runs", zs);
   for(i=0; i<7; i++)
   {
      strcat(query, ", ");
      strcat(query, (zs[i]=='1')?"1":"0");
   }

   EXTRACT("schedule_end_date", zs);
   time_t z = parse_datestamp(zs);
   sprintf(zs1, ", %ld", z);
   strcat(query, zs1);

   EXTRACT("signalling_id", signalling_id);
   sprintf(zs1, ", '%s'", signalling_id); strcat(query, zs1);

   EXTRACT_APPEND_SQL("CIF_train_category");
   EXTRACT_APPEND_SQL("CIF_headcode");
   //EXTRACT_APPEND_SQL("CIF_course_indicator");
   EXTRACT_APPEND_SQL("CIF_train_service_code");
   EXTRACT_APPEND_SQL("CIF_business_sector");
   EXTRACT_APPEND_SQL("CIF_power_type");
   EXTRACT_APPEND_SQL("CIF_timing_load");
   EXTRACT_APPEND_SQL("CIF_speed");
   EXTRACT_APPEND_SQL("CIF_operating_characteristics");
   EXTRACT_APPEND_SQL("CIF_train_class");

   EXTRACT_APPEND_SQL("CIF_sleepers");

   EXTRACT_APPEND_SQL("CIF_reservations");
   EXTRACT_APPEND_SQL("CIF_connection_indicator");
   EXTRACT_APPEND_SQL("CIF_catering_code");
   EXTRACT_APPEND_SQL("CIF_service_branding");
   
   EXTRACT("schedule_start_date", zs);
   z = parse_datestamp(zs);
   sprintf(zs1, ", %ld", z);
   strcat(query, zs1);

   EXTRACT_APPEND_SQL("train_status");

   strcat(query, ", 0, '', '')"); // id filled by MySQL

   if(!db_query(query))
   {
      stats[update?UpdateCreate:Create]++;
   }
      
   dword id = db_insert_id();

   word index = jsmn_find_name_token(string, tokens, 0, "schedule_location");
   word locations = tokens[index+1].size;

   huyton_flag = false;
   index += 2;
   for(i = 0; i < locations; i++)
   {
      index = process_create_schedule_location(string, tokens, index, id);
   }

   if(stp_indicator[0] == 'O' && (signalling_id[0] == '\0' || signalling_id[0] == ' '))
   {
      // Search db for schedules with a deduced headcode, and add it to this one, status = D
      // Bug:  Really this should also look for schedules with a signalling_id
      MYSQL_RES * result;
      MYSQL_ROW row;
      sprintf(query, "SELECT deduced_headcode FROM cif_schedules WHERE CIF_train_uid = '%s' AND deduced_headcode != '' AND schedule_end_date > %ld ORDER BY created DESC", uid, now - (64L * 24L * 60L * 60L));
      if(!db_query(query))
      {
         result = db_store_result();
         if((row = mysql_fetch_row(result)))
         {
            sprintf(query, "UPDATE cif_schedules SET deduced_headcode = '%s', deduced_headcode_status = 'D' WHERE id = %ld", row[0], id);
            db_query(query);
            _log(DEBUG, "Deduced headcode \"%s\" applied to overlay schedule %ld, uid \"%s\".", row[0], id, uid);
            stats[HeadcodeDeduced]++;
         }
         else
         {
            _log(DEBUG, "Deduced headcode not found for overlay schedule %ld, uid \"%s\".", id, uid);
         }
         mysql_free_result(result);
      }
   }

   sprintf(query, "UPDATE status SET last_vstp_processed = %ld", now);
   db_query(query);

   if(huyton_flag) 
   {
      _log(DEBUG, "Created schedule %ld%s.  +++ Passes Huyton +++", id, update?" as a result of an Update transaction":"");
   }

   if(huyton_flag)
   {
      char title[64], message[512];
      MYSQL_RES * result0;
      MYSQL_ROW row0;
      char stp[4];
      sprintf(title, "Huyton Schedule Created.");
      sprintf(message, "Created schedule which passes Huyton.");
      if(update) strcat(message, "  Due to a VSTP Update transaction.");
      strcat(message, "\n\n");
      EXTRACT("CIF_train_uid", zs1);
      EXTRACT("CIF_stp_indicator", stp);
      sprintf(zs, "%ld (%s %s) ", id, zs1, stp);
      EXTRACT("signalling_id", zs1);
      strcat(zs, zs1);
      sprintf(query, "SELECT tiploc_code, departure FROM cif_schedule_locations WHERE record_identity = 'LO' AND cif_schedule_id = %ld", id);
      if(!db_query(query))
      {
         result0 = db_store_result();
         if((row0 = mysql_fetch_row(result0)))
         {
            sprintf(zs1, " %s %s to ", show_time_text(row0[1]), tiploc_name(row0[0]));
            strcat(zs, zs1);
         }
         mysql_free_result(result0);
      }
      sprintf(query, "SELECT tiploc_code FROM cif_schedule_locations WHERE record_identity = 'LT' AND cif_schedule_id = %ld", id);
      if(!db_query(query))
      {
         result0 = db_store_result();
         if((row0 = mysql_fetch_row(result0)))
         {
            strcat (zs, tiploc_name(row0[0]));
         }
         mysql_free_result(result0);
      }

      strcat(message, zs);

      sprintf(query, "SELECT schedule_start_date, schedule_end_date, CIF_stp_indicator FROM cif_schedules WHERE id = %ld", id);
      if(!db_query(query))
      {
         result0 = db_store_result();
         if((row0 = mysql_fetch_row(result0)))
         {
            dword from = atol(row0[0]);
            dword to   = atol(row0[1]);
            if(from == to)
            {
               strcat(message, "  Runs on ");
               strcat(message, date_text(from, true));
            }
            else
            {
               strcat(message, "  Runs from ");
               strcat(message, date_text(from, true));
               strcat(message, " to ");
               strcat(message, date_text(to,   true));
            }
            if(row0[2][0] == 'C') strcat(message, "  CANCELLED");
            strcat(message, "\n");
         }
         mysql_free_result(result0);
      }
      sprintf(query, "SELECT departure, arrival, pass, tiploc_code FROM cif_schedule_locations WHERE (tiploc_code = 'HUYTON' OR tiploc_code = 'HUYTJUN') AND cif_schedule_id = %ld", id);
      if(!db_query(query))
      {
         result0 = db_store_result();
         while((row0 = mysql_fetch_row(result0)))
         {
            char where[32], z[128];
            if(row0[3][4] == 'J') strcpy(where, "Huyton Junction"); else strcpy(where, "Huyton"); 
            if(row0[0][0]) 
            {
               sprintf(z, "Depart %s at %s.\n", where, row0[0]);
               strcat(message, z);
            }
            else if(row0[1][0])
            {
               sprintf(z, "Arrive %s at %s.\n", where, row0[1]); 
               strcat(message, z);
            }
            else if(row0[2][0])
            {
               sprintf(z, "Pass %s at %s.\n", where, row0[2]);
               strcat(message, z);
            }
         }
         mysql_free_result(result0);
      }
      email_alert(NAME, BUILD, title, message);
   }
}
Example #3
0
int main(int argc, char **argv)
{
   char config_file_path[256];
   opt_filename = NULL;
   opt_url = NULL;
   fetch_all = false;
   test_mode = false;
   verbose = false;
   opt_insecure = false;
   used_insecure = false;

   strcpy(config_file_path, "/etc/openrail.conf");
   word usage = false;
   int c;
   while ((c = getopt (argc, argv, ":c:u:f:tpih")) != -1)
      switch (c)
      {
      case 'c':
         strcpy(config_file_path, optarg);
         break;
      case 'u':
         if(!opt_filename) opt_url = optarg;
         break;
      case 'f':
         if(!opt_url) opt_filename = optarg;
         break;
      case 'a':
         fetch_all = true;
         break;
      case 't':
         test_mode = true;
         break;
      case 'p':
         verbose = true;
         break;
      case 'i':
         opt_insecure = true;
         break;
      case 'h':
         usage = true;
         break;
      case ':':
         break;
      case '?':
      default:
         usage = true;
      break;
      }

   char * config_fail;
   if((config_fail = load_config(config_file_path)))
   {
      printf("Failed to read config file \"%s\":  %s\n", config_file_path, config_fail);
      usage = true;
   }

   if(usage) 
   {
      printf("%s %s  Usage: %s [-c /path/to/config/file.conf] [-u <url> | -f <path> | -a] [-t | -r] [-p][-i]\n", NAME, BUILD, argv[0]);
      printf(
             "-c <file>  Path to config file.\n"
             "Data source:\n"
             "default    Fetch latest update.\n"
             "-u <url>   Fetch from specified URL.\n"
             "-f <file>  Use specified file.  (Must already be decompressed.)\n"
             "Actions:\n"
             "default    Apply data to database.\n"
             "-t         Report datestamp on download or file, do not apply to database.\n"
             "Options:\n"
             "-i         Insecure.  Circumvent certificate checks if necessary.\n"
             "-p         Print activity as well as logging.\n"
             );
      exit(1);
   }

   char zs[1024];

   start_time = time(NULL);

   debug = *conf[conf_debug];
  
   _log_init(debug?"/tmp/tscdb.log":"/var/log/garner/tscdb.log", (debug?1:(verbose?4:0)));
   
   _log(GENERAL, "");
   _log(GENERAL, "%s %s", NAME, BUILD);
   
   // Enable core dumps
   struct rlimit limit;
   if(!getrlimit(RLIMIT_CORE, &limit))
   {
      limit.rlim_cur = RLIM_INFINITY;
      setrlimit(RLIMIT_CORE, &limit);
   }
   
   int i;
   for(i = 0; i < MATCHES; i++)
   {
      if(regcomp(&match[i], match_strings[i], REG_ICASE + REG_EXTENDED))
      {
         sprintf(zs, "Failed to compile regex match %d", i);
         _log(MAJOR, zs);
      }
   }
   
   // Initialise database
   if(db_init(conf[conf_db_server], conf[conf_db_user], conf[conf_db_password], conf[conf_db_name])) exit(1);

   {
      word e;
      if((e=database_upgrade(cifdb)))
      {
         _log(CRITICAL, "Error %d in upgrade_database().  Aborting.", e);
         exit(1);
      }
   }

   run = 1;
   tiploc_ignored = false;

   // Zero the stats
   {
      word i;
      for(i = 0; i < MAXStats; i++) { stats[i] = 0; }
   }

   if(fetch_file())
   {
      if(opt_url || opt_filename)
      {
         _log(GENERAL, "Failed to find data.");
         exit(1);
      }
      {
         char report[256];
         _log(GENERAL, "Failed to fetch file.");
         
         sprintf(report, "Failed to collect timetable update after %lld attempts.", stats[Fetches]);
         email_alert(NAME, BUILD, "Timetable Update Failure Report", report);
      }
      exit(1);
   }

   char in_q = 0;
   char b_depth = 0;

   size_t ibuf = 0;
   size_t iobj = 0;
   size_t buf_end;

   // Determine applicable update
   {
      MYSQL_RES * result0;
      MYSQL_ROW row0;
      last_update_id[0] = '\0';
      if(!db_query("SELECT MAX(id) FROM updates_processed"))
      {
         result0 = db_store_result();
         if((row0 = mysql_fetch_row(result0)))
         {
            strcpy(last_update_id, row0[0]);
         }
         mysql_free_result(result0);
      }
   }

   if(last_update_id[0] == '\0')
   {
      _log(CRITICAL, "Failed to determine last update id from database.");
      exit(1);
   }


   if(test_mode)
   {
   }
   else
   {
      char c, pc;
      pc = 0;
      // Run through the file splitting off each JSON object and passing it on for processing.

      // DB may have dropped out due to long delay
      (void) db_connect();
      if(db_start_transaction()) _log(CRITICAL, "Failed to initiate database transaction.");
      while((buf_end = fread(buffer, 1, MAX_BUF, fp_result)) && run && !db_errored)
      {
         for(ibuf = 0; ibuf < buf_end && run && !db_errored; ibuf++)
         {
            c = buffer[ibuf];
            if(c != '\r' && c != '\n') 
            {
               obj[iobj++] = c;
               if(iobj >= MAX_OBJ)
               {
                  _log(CRITICAL, "Object buffer overflow!");
                  exit(1);
               }
               if(c == '"' && pc != '\\') in_q = ! in_q;
               if(!in_q && c == '{') b_depth++;
               if(!in_q && c == '}' && b_depth-- && !b_depth)
               {
                  obj[iobj] = '\0';
                  process_object(obj);
                  iobj = 0;
               }
            }
            pc = c;
         }
      }
      fclose(fp_result);
      if(db_errored)
      {
         _log(CRITICAL, "Update rolled back due to database error.");
         (void) db_rollback_transaction();
      }
      else
      {
         _log(GENERAL, "Committing database updates...");
         if(db_commit_transaction())
         {
            _log(CRITICAL, "Database commit failed.");
         }
         else
         {
            _log(GENERAL, "Committed.");
         }
      }
   }

#define REPORT_SIZE 16384
   char report[REPORT_SIZE];
   report[0] = '\0';

   _log(GENERAL, "");
   _log(GENERAL, "End of run:");

   if(used_insecure)
   {
      strcat(report, "*** Warning: Insecure download used.\n");
      _log(GENERAL, "*** Warning: Insecure download used.");
   }

   sprintf(zs, "             Elapsed time: %ld minutes", (time(NULL) - start_time + 30) / 60);
   _log(GENERAL, zs);
   strcat(report, zs); strcat(report, "\n");
   if(test_mode)
   {
      sprintf(zs, "Test mode.  No database changes made.");
      _log(GENERAL, zs);
      strcat(report, zs); strcat(report, "\n");
      exit(0);
   }

   for(i=0; i<MAXStats; i++)
   {
      sprintf(zs, "%25s: %s", stats_category[i], commas_q(stats[i]));
      if(i == DBError && stats[i]) strcat(zs, " ****************");
      _log(GENERAL, zs);
      strcat(report, zs);
      strcat(report, "\n");
   }

   db_disconnect();

   email_alert(NAME, BUILD, "Timetable Update Report", report);

   exit(0);
}