예제 #1
0
static void process_vstp(const char * string, const jsmntok_t * tokens)
{
   char zs[128];

   stats[GoodMessage]++;

   jsmn_find_extract_token(string, tokens, 0, "transaction_type", zs, sizeof(zs));
   if(zs[0])
   {
      // printf("   Transaction type: \"%s\"", zs);
      if(!strcasecmp(zs, "Delete")) process_delete_schedule(string, tokens);
      else if(!strcasecmp(zs, "Create")) process_create_schedule(string, tokens, false);
      else if(!strcasecmp(zs, "Update")) process_update_schedule(string, tokens);
      else 
      {
         _log(MAJOR, "process_schedule():  Unrecognised transaction type \"%s\".", zs);
         jsmn_dump_tokens(body, tokens, 0);
         stats[NotTransaction]++;
      }
   }
   else
   {
      _log(MAJOR, "process_schedule():  Failed to determine transaction type.");
      jsmn_dump_tokens(body, tokens, 0);
      stats[NotTransaction]++;
   }
}
예제 #2
0
파일: tscdb.c 프로젝트: tinnerdxp/openrail
static void process_object(const char * object_string)
{
   // Passed a string containing a JSON object.
   // Parse it and process it.
   char zs[256];

   _log(PROC, "process_object()");

   jsmn_parser parser;
   jsmn_init(&parser);

   int r = jsmn_parse(&parser, object_string, tokens, MAX_TOKENS);
   if(r != JSMN_SUCCESS)
   {
      sprintf(zs, "Parser result %d.  ", r);
      
      switch(r)
      {
      case JSMN_SUCCESS:     strcat(zs, "Success.  "); break;
      case JSMN_ERROR_INVAL: strcat(zs, "Error - Invalid.  "); break;
      case JSMN_ERROR_NOMEM: strcat(zs, "Error - Nomem.  "); break;
      case JSMN_ERROR_PART:  strcat(zs, "Error - Part JSON.  "); break;
      default:               strcat(zs, "Unknown response.  "); break;
      }

      _log(MAJOR, zs);
      return;
   }

   if(tokens[1].type == JSMN_NAME)
   {
      char message_name[128];

      stats[JSONRecords]++; // NB This INCLUDES ones we don't use, like TiplocV1
      jsmn_extract_token(object_string, tokens, 1, message_name, sizeof(message_name));
      if(!strcmp(message_name, "JsonTimetableV1"))        process_timetable(object_string, tokens);
      else if(!strcmp(message_name, "JsonAssociationV1")) ;
      else if(!strcmp(message_name, "JsonScheduleV1"))    process_schedule(object_string, tokens);
      else if(!strcmp(message_name, "TiplocV1"))          ;
      else if(!strcmp(message_name, "EOF"))               ;
      else
      {
         _log(MINOR, "Unrecognised message name \"%s\".", message_name);
         jsmn_dump_tokens(object_string, tokens, 0);
         stats[JSONRecords]--;
      }
   }
   else
   {
      _log(MAJOR, "Unrecognised message.");
      jsmn_dump_tokens(object_string, tokens, 0);
   }
   return;
}
예제 #3
0
static void process_frame(const char * body)
{
   jsmn_parser parser;
   time_t elapsed = time(NULL);
   
   jsmn_init(&parser);
   int r = jsmn_parse(&parser, body, tokens, NUM_TOKENS);
   if(r != 0) 
   {
      _log(MAJOR, "Parser result %d.  Message discarded.", r);
      stats[NotVSTP]++;
   }
   else
   {
      // Good message
      char message_name[128];
      jsmn_extract_token(body, tokens, 1, message_name, sizeof(message_name));
      if(!strcmp(message_name, "VSTPCIFMsgV1")) 
      {
         process_vstp(body, tokens);
      }
      else
      {
         _log(MINOR, "Unrecognised message name \"%s\".", message_name);
         jsmn_dump_tokens(body, tokens, 0);
         stats[NotVSTP]++;
      }
   }
   elapsed = time(NULL) - elapsed;
   if(elapsed > 1 || debug)
   {
      _log(MINOR, "Transaction took %ld seconds.", elapsed);
   }
}
예제 #4
0
static void process_update_schedule(const char * string, const jsmntok_t * tokens)
{
   char query[1024], CIF_train_uid[16], schedule_start_date[16], schedule_end_date[16], CIF_stp_indicator[8]; 
   dword id;
   MYSQL_RES * result0;
   MYSQL_ROW row0;

   EXTRACT("CIF_train_uid", CIF_train_uid);
   EXTRACT("schedule_start_date", schedule_start_date);
   EXTRACT("schedule_end_date", schedule_end_date);
   EXTRACT("CIF_stp_indicator", CIF_stp_indicator);

   time_t schedule_start_date_stamp = parse_datestamp(schedule_start_date);
   // time_t schedule_end_date_stamp   = parse_datestamp(schedule_end_date);

   sprintf(query, "SELECT id FROM cif_schedules WHERE update_id = 0 AND CIF_train_uid = '%s' AND CIF_stp_indicator = '%s' AND schedule_start_date = %ld AND deleted > %ld", CIF_train_uid, CIF_stp_indicator, schedule_start_date_stamp, time(NULL));
   if(!db_query(query))
   {
      result0 = db_store_result();
      word num_rows = mysql_num_rows(result0);
      if(num_rows != 1)
      {
         _log(MAJOR, "Update for schedule \"%s\" found %d existing records.  Delete phase skipped.", CIF_train_uid, num_rows);
         jsmn_dump_tokens(string, tokens, 0);
         if(num_rows) stats[UpdateDeleteMulti]++; else stats[UpdateDeleteMiss]++;
      }
      else
      {
         row0 = mysql_fetch_row(result0);
         id = atol(row0[0]);
         //sprintf(query, "DELETE FROM cif_schedule_locations WHERE cif_schedule_id = %ld", id);
         //db_query(query);
         sprintf(query, "UPDATE cif_schedules SET deleted = %ld WHERE id = %ld", time(NULL), id);
         db_query(query);
      }
      mysql_free_result(result0);
   }

   // Create phase.
   process_create_schedule(string, tokens, true);

   _log(DEBUG, "Updated schedule \"%s\".", CIF_train_uid);
}
예제 #5
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);
   }
}
예제 #6
0
static void process_delete_schedule(const char * string, const jsmntok_t * tokens)
{
   char query[1024], CIF_train_uid[16], schedule_start_date[16], schedule_end_date[16], CIF_stp_indicator[8]; 
   dword id;
   word update_id;
   MYSQL_RES * result0;
   MYSQL_ROW row0;

   word deleted = 0;

   EXTRACT("CIF_train_uid", CIF_train_uid);
   EXTRACT("schedule_start_date", schedule_start_date);
   EXTRACT("schedule_end_date", schedule_end_date);
   EXTRACT("CIF_stp_indicator", CIF_stp_indicator);

   time_t schedule_start_date_stamp = parse_datestamp(schedule_start_date);
   time_t schedule_end_date_stamp   = parse_datestamp(schedule_end_date);

   // Find the id
   sprintf(query, "SELECT id, update_id FROM cif_schedules where CIF_train_uid = '%s' and schedule_start_date = '%ld' and schedule_end_date = %ld and CIF_stp_indicator = '%s' AND update_id = 0 AND deleted > %ld",
           CIF_train_uid, schedule_start_date_stamp, schedule_end_date_stamp, CIF_stp_indicator, time(NULL));

   // DO WE NEED DAYS RUNS AS WELL????
   // Note:  Only find VSTP ones.

   if (db_query(query))
   {
      db_disconnect();
      return;
   }

   result0 = db_store_result();
   word num_rows = mysql_num_rows(result0);

   if(num_rows > 1)
   {
      char zs[256];
      sprintf(zs, "Delete schedule found %d matches.", num_rows);
      _log(MAJOR, zs);
      jsmn_dump_tokens(string, tokens, 0);
      stats[DeleteMulti]++;
      // Bodge!
      query[7] = '*'; query[8] = ' ';
      dump_mysql_result_query(query);
   }
 
   while((row0 = mysql_fetch_row(result0)) && row0[0]) 
   {
      id = atol(row0[0]);
      update_id = atoi(row0[1]);

      //sprintf(query, "DELETE FROM cif_schedule_locations WHERE cif_schedule_id = %ld", id);
      //if(!db_query(query))
      //{
      //}

      sprintf(query, "UPDATE cif_schedules SET deleted = %ld where id = %ld", time(NULL), id);
   
      if(!db_query(query))
      {
         deleted++;
         if(update_id)
         {
            // Can never happen!
            _log(MAJOR, "Deleted non-VSTP schedule %ld.", id);
         }
         else
         {
            _log(DEBUG, "Deleted VSTP schedule %ld \"%s\".", id, CIF_train_uid);
         }
      }
   }
   mysql_free_result(result0);

   if(deleted) 
   {
      stats[DeleteHit]++;
   }
   else
   {
      _log(MAJOR, "Delete schedule miss.");
      jsmn_dump_tokens(string, tokens, 0);
      stats[DeleteMiss]++;
   }
}
예제 #7
0
static void process_trust_0001(const char * const string, const jsmntok_t * const tokens, const int index)
{
   char zs[128], zs1[128], report[1024];
   char train_id[64], train_uid[64];
   char query[1024];
   dword cif_schedule_id;
   MYSQL_RES * result0;
   MYSQL_ROW row0;
   
   sprintf(report, "Activation message:");

   jsmn_find_extract_token(string, tokens, index, "train_id", train_id, sizeof(train_id));
   sprintf(zs1, " train_id=\"%s\"", train_id);
   strcat(report, zs1);

   jsmn_find_extract_token(string, tokens, index, "schedule_start_date", zs, sizeof(zs));
   time_t schedule_start_date_stamp = parse_datestamp(zs);
   sprintf(zs1, " schedule_start_date=\"%s\" %ld", zs, schedule_start_date_stamp);
   strcat(report, zs1);

   jsmn_find_extract_token(string, tokens, index, "schedule_end_date", zs, sizeof(zs));
   time_t schedule_end_date_stamp   = parse_datestamp(zs);
   sprintf(zs1, " schedule_end_date=\"%s\" %ld", zs, schedule_end_date_stamp);
   strcat(report, zs1);

   jsmn_find_extract_token(string, tokens, index, "train_uid", train_uid, sizeof(train_uid));
   sprintf(zs1, " train_uid=\"%s\"", train_uid);
   strcat(report, zs1);

   jsmn_find_extract_token(string, tokens, index, "schedule_source", zs, sizeof(zs));
   sprintf(zs1, " schedule_source=\"%s\"", zs);
   strcat(report, zs1);

   jsmn_find_extract_token(string, tokens, index, "schedule_wtt_id", zs, sizeof(zs));
   sprintf(zs1, " schedule_wtt_id=\"%s\"", zs);
   strcat(report, zs1);

   // Bodge.  The ORDER BY here will *usually* get the correct one out first!
   // Idea:  If we store and index on cif_train_uid, we can guarantee to get the right one.
   sprintf(query, "select id from cif_schedules where cif_train_uid = '%s' AND schedule_start_date = %ld AND schedule_end_date = %ld AND deleted > %ld ORDER BY LOCATE(CIF_stp_indicator, 'OCPN')", train_uid, schedule_start_date_stamp, schedule_end_date_stamp, time(NULL));
   if(!db_query(query))
   {
      result0 = db_store_result();
      word num_rows = mysql_num_rows(result0);
      sprintf(zs, "  Schedule hit count %d.  Message contents:", num_rows);
      strcat(report, zs);
      if(num_rows < 1) 
      {
         stats[Mess1Miss]++;
         _log(MINOR, report);
         time_t now = time(NULL);
         sprintf(query, "INSERT INTO trust_activation VALUES(%ld, '%s', %ld, 0)", now, train_id, 0L);
         db_query(query);
         jsmn_dump_tokens(string, tokens, index);
      }
      else
      {
         row0 = mysql_fetch_row(result0);
         cif_schedule_id = atol(row0[0]);
         time_t now = time(NULL);
         sprintf(query, "INSERT INTO trust_activation VALUES(%ld, '%s', %ld, 0)", now, train_id, cif_schedule_id);
         db_query(query);
      }
      mysql_free_result(result0);
   }
   return;
}
예제 #8
0
static void process_message(const char * const body)
{
   jsmn_parser parser;
   time_t elapsed = time(NULL);
   
   log_message(body);

   jsmn_init(&parser);
   int r = jsmn_parse(&parser, body, tokens, NUM_TOKENS);
   if(r != 0) 
   {
      sprintf(zs, "Parser result %d.  Message discarded.", r);
      _log(MAJOR, zs);
      stats[NotRecog]++;
   }
   else
   {
      size_t messages, i, index;
      // Is it an array?
      if(tokens[0].type == JSMN_ARRAY)
      {
         messages = tokens[0].size;
         index = 1;
         sprintf(zs, "STOMP message is array of %d TRUST messages.", messages);
      }
      else
      {
         messages = 1;
         index = 0;
         sprintf(zs, "STOMP message contains a single TRUST message.");
      }
      _log(DEBUG,zs);

      for(i=0; i < messages; i++)
      {
         char message_name[128];
         jsmn_find_extract_token(body, tokens, index, "msg_type", message_name, sizeof(message_name));
         word message_type = atoi(message_name);
         if(debug)
         {
            sprintf(zs, "Processing TRUST message %d", i);
            _log(DEBUG, zs);
         }
         if(!strncmp(message_name, "000", 3) && message_type > 0 && message_type < 9) 
         {
            stats[GoodMessage]++;
            stats[GoodMessage + message_type]++;
            switch(message_type)
            {
            case 1: process_trust_0001(body, tokens, index); break;
            case 2: process_trust_0002(body, tokens, index); break;
            case 3: process_trust_0003(body, tokens, index); break;
            case 5: process_trust_0005(body, tokens, index); break;
            case 6: process_trust_0006(body, tokens, index); break;
            case 7: process_trust_0007(body, tokens, index); break;
            default:
               sprintf(zs, "Message type \"%s\" discarded.", message_name);
               _log(MINOR, zs);
               break;
            }
         }
         else
         {
            sprintf(zs, "Unrecognised message type \"%s\".", message_name);
            _log(MINOR, zs);
            jsmn_dump_tokens(body, tokens, index);
            stats[NotRecog]++;
         }
         
         size_t message_ends = tokens[index].end;
         do  index++; 
         while ( tokens[index].start < message_ends && tokens[index].start >= 0 && index < NUM_TOKENS);
      }
   }
   elapsed = time(NULL) - elapsed;
   if(debug || elapsed > 1)
   {
      char zs[128];
      sprintf(zs, "Transaction took %ld seconds.", elapsed);
      _log(MINOR, zs);
   }
}