Esempio n. 1
0
/*
 * The event scheduler and resource ticker.
 */
static void run_ticker (db_t *database)
{
  time_t last = time(NULL);
  int events = 0, sleeps = 0;

  debug(DEBUG_TICKER, "running");

  while (!finish) {
    /* set up memory pool */
    struct memory_pool *pool = memory_pool_new();
    time_t now = time(NULL);
    int secs = now - last;

    if (secs >= TICKER_LOADAVG_TIME)
    {
	debug(DEBUG_TICKER, "ticker load: %.2f (%d events/min)",
	      1 - sleep_time / 1000000.0 * sleeps / secs, 60 * events / secs);

	events = sleeps = 0;
	last = now;
#ifdef DEBUG_MALLOC
	CHECK_LEAKS();
#endif
    }

    if (reload)
    {
	debug(DEBUG_TICKER, "reload config");
	reload = 0;

	/* read config file */
	config_read_file(config_file);
	fetch_config_values();
	log_handler_set_file(debug_log, debug_logfile);
	log_handler_set_file(error_log, error_logfile);
	log_handler_set_file(msg_log, msg_logfile);
    }

    try {
      char resource_timestamp[TIMESTAMP_LEN];
      char timestamp[TIMESTAMP_LEN];
      db_result_t *next_result = NULL;
      const char *next_timestamp =
	make_timestamp_gm(resource_timestamp, tick_next_event());
      const char *next_db_eventID;
      int next_eventType;
      int i;

      /* check each event queue to find the next event to process */
      debug(DEBUG_EVENTS, "start loop, next resource event");

      for (i = 0; i < eventTableSize; ++i)
      {
	db_result_t *result;

	/* get only the next non-blocked event, if its timestamp
	   is smaller than the smallest found timestamp */
	debug(DEBUG_EVENTS, "query event table: %s", eventTableList[i].table);
//	debug(DEBUG_TICKER, "query event table: %s", eventTableList[i].table);

	result = db_query(database,
		    "SELECT * FROM %s WHERE blocked = 0 AND end < '%s' "
		    "ORDER BY end ASC, %s ASC LIMIT 0,1",
		    eventTableList[i].table, next_timestamp,
		    eventTableList[i].id_field);

	if (db_result_num_rows(result))	/* is there an earlier event? */
	{
	  /* extract this earlier event's needed data */
	  db_result_next_row(result);

	  next_result = result;		/* remember the earlier one */
	  next_timestamp = db_result_get_string(result, "end");
	  next_db_eventID =
	    db_result_get_string(result, eventTableList[i].id_field);
	  next_eventType = i;
	}
      }

      if (strcmp(next_timestamp, make_timestamp_gm(timestamp, time(NULL))) > 0)
      {
	debug(DEBUG_EVENTS, "no event pending, sleep");
	++sleeps;
	usleep(sleep_time);
      }
      else
      {
	debug(DEBUG_TICKER, "event: scheduled %s, now %s",
	      next_timestamp, timestamp);

	/* check which handler to call (resource ticker or event handler) */
	if (next_result)
	{
	  /* found an event in the event tables: block the event */
	  debug(DEBUG_EVENTS, "block event: %s", next_db_eventID);
	  ++events;

	  db_query(database, "UPDATE %s SET blocked = 1 WHERE %s = %s",
			  eventTableList[next_eventType].table,
			  eventTableList[next_eventType].id_field,
			  next_db_eventID);

	  /* call handler and delete event */
	  eventTableList[next_eventType].handler(database, next_result);

	  debug(DEBUG_EVENTS_DELETE, "delete event: %s", next_db_eventID);

	  db_query(database, "DELETE FROM %s WHERE %s = %s",
			  eventTableList[next_eventType].table,
			  eventTableList[next_eventType].id_field,
			  next_db_eventID);
	}
	else
	{
	  /* next event is resource tick: call resource ticker */
	  debug(DEBUG_TICKER, "resource tick %s", resource_timestamp);

	  resource_ticker(database, tick_advance());
	  debug(DEBUG_TICKER, "resource tick ended");
	  tick_log();			/* log last successful update */
	}
      }
    } catch (BAD_ARGUMENT_EXCEPTION) {
      warning("%s", except_msg);
    } catch (SQL_EXCEPTION) {
      warning("%s", except_msg);
    } catch (GENERIC_EXCEPTION) {
      warning("%s", except_msg);
    } catch (DB_EXCEPTION) {
      block_ticker(except_msg);
    } catch (NULL) {
      error("%s", except_msg);
    } end_try;

    memory_pool_free(pool);
  }

  debug(DEBUG_TICKER, "end");
}
Esempio n. 2
0
/*
 * merge_artefacts_special
 * Throws exception if needed conditions are not as they should have been.
 */
int merge_artefacts_special (db_t *database,
			     const struct Artefact *key_artefact,
			     struct Artefact *lock_artefact,
			     struct Artefact *result_artefact)
{
  db_result_t *result;
  db_result_t *temp_result;
  int row;

  /* get merging formulas */
  result = db_query(database, "SELECT * FROM Artefact_merge_special "
			      "WHERE keyID = %d", key_artefact->artefactID);

  /* check for a suitable merging formula */
  while ((row = db_result_next_row(result)))
  {
    /* some special cases:
     *
     * lockID == 0 || keyID == lockID
     * no lock artefact needed; key artefact transforms directly
     *
     * resultID == 0
     * key and lock artefacts just vanish
     */

    /* lock artefact */
    lock_artefact->artefactID = db_result_get_int(result, "lockID");

    /* special cases: lockID == 0 || keyID == lockID (no lock required) */
    if (lock_artefact->artefactID == 0 ||
	lock_artefact->artefactID == key_artefact->artefactID)
      break;

    /* get lock_artefact */
    /* throws exception, if that artefact is missing */
    get_artefact_by_id(database, lock_artefact->artefactID, lock_artefact);

    /* check: key and lock have to be in the same cave and initiated */
    if (lock_artefact->caveID == key_artefact->caveID &&
	lock_artefact->initiated == ARTEFACT_INITIATED)
      break;
  }

  if (row)
  {
    /* result artefact */
    result_artefact->artefactID = db_result_get_int(result, "resultID");

    /* special case: resultID == 0 */
    if (result_artefact->artefactID != 0)
    {
      /* get result_artefact */
      /* throws exception, if that artefact is missing */
      get_artefact_by_id(database, result_artefact->artefactID, result_artefact);

      /* check: result_artefact must not be in any cave */
      if (result_artefact->caveID != 0)
        throwf(BAD_ARGUMENT_EXCEPTION,
	       "merge_artefacts_special: result artefact %d is in cave %d",
               result_artefact->artefactID, result_artefact->caveID);

      /* result_artefact must not be in any movement */
      temp_result = db_query(database, "SELECT * FROM Event_movement"
				       " WHERE artefactID = %d",
			     result_artefact->artefactID);

      if (db_result_num_rows(temp_result) != 0)
        throwf(BAD_ARGUMENT_EXCEPTION,
	       "merge_artefacts_special: result artefact %d is moving",
               result_artefact->artefactID);

      /* check: result_artefact has to be uninitiated */
      /* XXX can this ever happen (it is not in a cave)? */
      if (result_artefact->initiated != ARTEFACT_UNINITIATED)
        uninitiate_artefact(database, result_artefact->artefactID);
    }

    /* now merge them */
    merge_artefacts(database,
                    key_artefact->caveID,
                    key_artefact->artefactID,
                    lock_artefact->artefactID,
                    result_artefact->artefactID);
    return 1;
  }

  return 0;
}