New update scheduler:
(schedulefil): New. (set_dirs, set_paths): Rename. Initialize schedulfil. (read_schedule): New. Can read several updates, which will be used in later changesets. (update_time): Change to array. Will be used in later changesets. (update_schedule_anchor): New. (update_init): Initialize it. (update_get_schedule): New. (update_init): Call it to initialize update_time[]. (update_sched): Rewrite. (update_forced, update_wanted): Replace. (update_reschedule): New. (main): Call it on SIGHUP to reload the schedule. (update_trigger, update_force, force, player_coms): Drop force's capability to schedule updates in the future, because it's not worth the trouble to implement again. Deities can simply edit the schedule file to schedule updates. Remove update_force() and update_trigger()'s parameter. (upda): Update for new scheduler. Take care to keep output the same as far as possible, even though it's ugly, to avoid breaking clients. (update_policy, adj_update, update_times, hourslop, blitz_time): econfig keys removed. (update_demand, UPD_DEMAND_NONE, UPD_DEMAND_SCHED, UPD_DEMAND_ASYNC) (update_demandpolicy, UDP_NORMAL, UDP_TIMES, UDP_NORMAL, UDP_BLITZ) (UDP_MAX, UDP_DEFAULT, UDDEM_TMCHECK, UDDEM_COMSET, UDDEM_DISABLE) (UDDEM_MAX, UDDEM_DEFAULT): econfig key and values replaced. Users changed. wantupd.h is now empty, remove. (demand_check): External linkage. (update_policy_check): Now pointless, remove. (is_daytime_near, min_to_next_daytime, regular_update_time) (scheduled_update_time, next_scheduled_time, updatetime) (next_update_time, next_update_check_time): Unused, Remove. (demand_check, demandupdatecheck): Move call of demand_update_time() from demand_check(), which controls all demand updates, to demandupdatecheck(), which controls only unscheduled ones. Fixes update command not to lie about the next scheduled demand update. (demandupdatecheck): Check updates_disabled() so that zdone no longer claims to trigger an update when it can't.
This commit is contained in:
parent
15f8f48353
commit
71320ed67f
20 changed files with 487 additions and 448 deletions
|
@ -101,46 +101,34 @@ EMPCFBOTH("WORLD_X", WORLD_X, int, NSC_INT, 0,
|
||||||
EMPCFBOTH("WORLD_Y", WORLD_Y, int, NSC_INT, 0,
|
EMPCFBOTH("WORLD_Y", WORLD_Y, int, NSC_INT, 0,
|
||||||
"World size Y dimension")
|
"World size Y dimension")
|
||||||
|
|
||||||
EMPCF_COMMENT("\n\n### Update policy")
|
EMPCF_COMMENT("\n\n### Update policy\n\n"
|
||||||
EMPCFBOTH("update_policy", update_policy, int, NSC_INT, 0,
|
"# Note: the update schedule is defined in the file schedule in the\n"
|
||||||
"Update policy")
|
"# same directory as this file.")
|
||||||
EMPCF_COMMENT("# 0 - Schedule updates according to etu_per_update, s_p_etu, adj_update\n"
|
|
||||||
"# 1 - Update at times specified by key \"update_times\"\n"
|
|
||||||
"# 2 - Blitz update every blitz_time minute\n"
|
|
||||||
"# 3 - No regular updates, only demand ones")
|
|
||||||
EMPCFBOTH("etu_per_update", etu_per_update, int, NSC_INT, 0,
|
EMPCFBOTH("etu_per_update", etu_per_update, int, NSC_INT, 0,
|
||||||
"Number of ETUs per update")
|
"Number of ETUs per update")
|
||||||
EMPCFBOTH("s_p_etu", s_p_etu, int, NSC_INT, 0,
|
EMPCFBOTH("s_p_etu", s_p_etu, int, NSC_INT, 0,
|
||||||
"Seconds per ETU")
|
"Seconds per ETU")
|
||||||
EMPCF_COMMENT("# updates under policy 0 occur every s_p_etu * etu_per_update seconds")
|
EMPCF_COMMENT("# FIXME get rid of this!\n"
|
||||||
EMPCFBOTH("adj_update", adj_update, int, NSC_INT, KM_INTERNAL,
|
"# Until then, set it so that s_p_etu * etu_per_update seconds equals\n"
|
||||||
"Move the update forward or backward (in seconds)")
|
"# the time between scheduled updates.")
|
||||||
EMPCFBOTH("update_window", update_window, int, NSC_INT, 0,
|
EMPCFBOTH("update_window", update_window, int, NSC_INT, 0,
|
||||||
"Window the update will occur in (in seconds) before and after the update time")
|
"Time window the update will occur in after the update time, in seconds")
|
||||||
EMPCFBOTH("update_times", update_times, char *, NSC_STRING, 0,
|
|
||||||
"Times of day when updates may occur under policy 1, separated by space.")
|
|
||||||
EMPCF_COMMENT("# Give time of day as HOUR:MINUTE, e.g. 20:00\n"
|
|
||||||
"# Times must coincide with updates under policy 0.")
|
|
||||||
EMPCFBOTH("hourslop", hourslop, int, NSC_INT, KM_INTERNAL,
|
|
||||||
"Number of minutes update check can slip to match update_times")
|
|
||||||
EMPCFBOTH("blitz_time", blitz_time, int, NSC_INT, 0,
|
|
||||||
"Number of minutes between updates under policy 2.")
|
|
||||||
EMPCFBOTH("pre_update_hook", pre_update_hook, char *, NSC_STRING, KM_INTERNAL,
|
EMPCFBOTH("pre_update_hook", pre_update_hook, char *, NSC_STRING, KM_INTERNAL,
|
||||||
"Shell command run right before the update.")
|
"Shell command run right before the update.")
|
||||||
|
|
||||||
EMPCF_COMMENT("\n\n### Demand update policy")
|
EMPCFBOTH("update_demand", update_demand, int, NSC_INT, 0,
|
||||||
EMPCFBOTH("update_demandpolicy", update_demandpolicy, int, NSC_INT, 0,
|
|
||||||
"Demand update policy")
|
"Demand update policy")
|
||||||
EMPCF_COMMENT("# 0 - Votes tallied at update times under policy 0\n"
|
EMPCF_COMMENT("# 0 - No demand updates\n"
|
||||||
"# 1 - Votes tallies right after a vote\n"
|
"# 1 - Scheduled updates are demand updates\n"
|
||||||
"# 2 - Demand updates disabled")
|
"# 2 - Demand updates run right after the deciding vote is cast,\n"
|
||||||
|
"# in addition to (non-demand) scheduled updates\n")
|
||||||
EMPCFBOTH("update_wantmin", update_wantmin, int, NSC_INT, 0,
|
EMPCFBOTH("update_wantmin", update_wantmin, int, NSC_INT, 0,
|
||||||
"Number of votes required for a demand update")
|
"Number of votes required for a demand update")
|
||||||
EMPCFBOTH("update_missed", update_missed, int, NSC_INT, 0,
|
EMPCFBOTH("update_missed", update_missed, int, NSC_INT, 0,
|
||||||
"A country vetoes further demand updates after missing that many votes")
|
"A country vetoes further demand updates after missing that many votes")
|
||||||
EMPCFBOTH("update_demandtimes", update_demandtimes, char *, NSC_STRING, 0,
|
EMPCFBOTH("update_demandtimes", update_demandtimes, char *, NSC_STRING, 0,
|
||||||
"Time of day ranges when demand updates can occur, separated by space.")
|
"Times when unscheduled demand updates can occur, separated by space.")
|
||||||
EMPCF_COMMENT("# Give range HOUR:MINUTE-HOUR:MINUTE, e.g. 20:00-24:00\n"
|
EMPCF_COMMENT("# Give time ranges as HOUR:MINUTE-HOUR:MINUTE, e.g. 20:00-24:00\n"
|
||||||
"# Ranges CANNOT cross midnight.")
|
"# Ranges CANNOT cross midnight.")
|
||||||
|
|
||||||
EMPCF_COMMENT("\n\n### Game hours restrictions")
|
EMPCF_COMMENT("\n\n### Game hours restrictions")
|
||||||
|
@ -149,7 +137,7 @@ EMPCFBOTH("game_days", game_days, char *, NSC_STRING, 0,
|
||||||
EMPCF_COMMENT("# Give days as Su Mo Tu We Th Fr Sa.")
|
EMPCF_COMMENT("# Give days as Su Mo Tu We Th Fr Sa.")
|
||||||
EMPCFBOTH("game_hours", game_hours, char *, NSC_STRING, 0,
|
EMPCFBOTH("game_hours", game_hours, char *, NSC_STRING, 0,
|
||||||
"Time of day ranges when the game is open, separated by space.")
|
"Time of day ranges when the game is open, separated by space.")
|
||||||
EMPCF_COMMENT("# Give range HOUR:MINUTE-HOUR:MINUTE, e.g. 20:00-24:00\n"
|
EMPCF_COMMENT("# Give time ranges as HOUR:MINUTE-HOUR:MINUTE, e.g. 20:00-24:00\n"
|
||||||
"# Ranges CANNOT cross midnight.")
|
"# Ranges CANNOT cross midnight.")
|
||||||
|
|
||||||
EMPCF_COMMENT("\n\n### Options")
|
EMPCF_COMMENT("\n\n### Options")
|
||||||
|
|
|
@ -45,6 +45,7 @@ extern char dflt_econfig[];
|
||||||
#undef EMP_CONFIG_H_OUTPUT
|
#undef EMP_CONFIG_H_OUTPUT
|
||||||
|
|
||||||
extern char *configdir;
|
extern char *configdir;
|
||||||
|
extern char *schedulefil;
|
||||||
|
|
||||||
extern char motdfil[];
|
extern char motdfil[];
|
||||||
extern char downfil[];
|
extern char downfil[];
|
||||||
|
@ -60,6 +61,12 @@ enum {
|
||||||
KM_OPTION = 4 /* historically an option */
|
KM_OPTION = 4 /* historically an option */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
UPD_DEMAND_NONE, /* no demand updates */
|
||||||
|
UPD_DEMAND_SCHED, /* scheduled updates are demand updates */
|
||||||
|
UPD_DEMAND_ASYNC, /* zdone triggers unscheduled update */
|
||||||
|
};
|
||||||
|
|
||||||
struct keymatch {
|
struct keymatch {
|
||||||
char *km_key; /* the key */
|
char *km_key; /* the key */
|
||||||
nsc_type km_type; /* type of associated data */
|
nsc_type km_type; /* type of associated data */
|
||||||
|
|
|
@ -298,8 +298,6 @@ extern double hap_req(struct natstr *np);
|
||||||
extern int is_wday_allowed(int, char *);
|
extern int is_wday_allowed(int, char *);
|
||||||
extern int is_daytime_allowed(int, char *);
|
extern int is_daytime_allowed(int, char *);
|
||||||
extern int gamehours(time_t);
|
extern int gamehours(time_t);
|
||||||
extern int is_daytime_near(int, char *, int);
|
|
||||||
extern int min_to_next_daytime(int, char *);
|
|
||||||
/* land.c */
|
/* land.c */
|
||||||
extern int has_units(coord, coord, natid, struct lndstr *);
|
extern int has_units(coord, coord, natid, struct lndstr *);
|
||||||
extern int has_units_with_mob(coord, coord, natid);
|
extern int has_units_with_mob(coord, coord, natid);
|
||||||
|
@ -332,6 +330,8 @@ extern char *BestLandPath(char *, struct sctstr *, struct sctstr *,
|
||||||
extern char *BestShipPath(char *, int, int, int, int, int);
|
extern char *BestShipPath(char *, int, int, int, int, int);
|
||||||
extern char *BestAirPath(char *, int, int, int, int);
|
extern char *BestAirPath(char *, int, int, int, int);
|
||||||
extern double pathcost(struct sctstr *, char *, int);
|
extern double pathcost(struct sctstr *, char *, int);
|
||||||
|
/* rdsched.c */
|
||||||
|
extern int read_schedule(char *, time_t[], int, time_t, time_t);
|
||||||
/* res_pop.c */
|
/* res_pop.c */
|
||||||
extern int max_population(float, int, int);
|
extern int max_population(float, int, int);
|
||||||
extern int max_pop(float, struct sctstr *);
|
extern int max_pop(float, struct sctstr *);
|
||||||
|
@ -343,12 +343,9 @@ extern int sectdamage(struct sctstr *, int, struct emp_qelem *);
|
||||||
/* type.c */
|
/* type.c */
|
||||||
extern int sct_typematch(char *);
|
extern int sct_typematch(char *);
|
||||||
/* wantupd.c */
|
/* wantupd.c */
|
||||||
extern void update_policy_check(void);
|
|
||||||
extern int demand_update_want(int *, int *, int);
|
extern int demand_update_want(int *, int *, int);
|
||||||
|
extern int demand_check(void);
|
||||||
extern int demandupdatecheck(void);
|
extern int demandupdatecheck(void);
|
||||||
extern int updatetime(time_t *);
|
|
||||||
extern void next_update_time(time_t *, time_t *, time_t *);
|
|
||||||
extern void next_update_check_time(time_t *, time_t *, time_t *);
|
|
||||||
extern int updates_disabled(void);
|
extern int updates_disabled(void);
|
||||||
/* xundump.c */
|
/* xundump.c */
|
||||||
extern int xundump(FILE *, char *, int);
|
extern int xundump(FILE *, char *, int);
|
||||||
|
|
|
@ -39,14 +39,15 @@
|
||||||
extern int shutdown_pending;
|
extern int shutdown_pending;
|
||||||
extern int update_pending;
|
extern int update_pending;
|
||||||
extern empth_rwlock_t *update_lock;
|
extern empth_rwlock_t *update_lock;
|
||||||
extern time_t update_time;
|
extern time_t update_time[];
|
||||||
extern int updating_mob;
|
extern int updating_mob;
|
||||||
|
|
||||||
void mobility_init(void);
|
void mobility_init(void);
|
||||||
void market_init(void);
|
void market_init(void);
|
||||||
void update_main(void);
|
void update_main(void);
|
||||||
void update_init(void);
|
void update_init(void);
|
||||||
int update_trigger(time_t);
|
int update_trigger(void);
|
||||||
|
int update_reschedule(void);
|
||||||
int shutdown_initiate(int);
|
int shutdown_initiate(int);
|
||||||
|
|
||||||
/* thread entry points */
|
/* thread entry points */
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* Empire - A multi-player, client/server Internet based war game.
|
|
||||||
* Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
|
|
||||||
* Ken Stevens, Steve McClure
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* ---
|
|
||||||
*
|
|
||||||
* See files README, COPYING and CREDITS in the root of the source
|
|
||||||
* tree for related information and legal notices. It is expected
|
|
||||||
* that future projects/authors will amend these files as needed.
|
|
||||||
*
|
|
||||||
* ---
|
|
||||||
*
|
|
||||||
* wantupd.h: Header used to check to see if an update is wanted
|
|
||||||
* and/or allowed.
|
|
||||||
*
|
|
||||||
* Known contributors to this file:
|
|
||||||
* Doug Hay, 1991
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WANTUPD_H
|
|
||||||
#define WANTUPD_H
|
|
||||||
|
|
||||||
/* Update policies */
|
|
||||||
#define UDP_NORMAL 0
|
|
||||||
#define UDP_TIMES 1
|
|
||||||
#define UDP_NOREG 3
|
|
||||||
#define UDP_BLITZ 2
|
|
||||||
#define UDP_MAX 3
|
|
||||||
#define UDP_DEFAULT UDP_NORMAL
|
|
||||||
|
|
||||||
/* Demand update policies */
|
|
||||||
#define UDDEM_TMCHECK 0
|
|
||||||
#define UDDEM_COMSET 1
|
|
||||||
#define UDDEM_DISABLE 2
|
|
||||||
#define UDDEM_MAX 2
|
|
||||||
#define UDDEM_DEFAULT UDDEM_DISABLE
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,6 +1,6 @@
|
||||||
.TH Command FORCE
|
.TH Command FORCE
|
||||||
.NA force "Force an update"
|
.NA force "Force an update"
|
||||||
.LV Expert
|
.LV Expert
|
||||||
.SY "force <seconds>"
|
.SY "force"
|
||||||
Force an update in <seconds> seconds.
|
Force an update now.
|
||||||
.SA "enable, disable, shutdown, Deity"
|
.SA "enable, disable, reload, shutdown, Deity"
|
||||||
|
|
|
@ -81,7 +81,8 @@ deprecated.
|
||||||
.B SIGHUP
|
.B SIGHUP
|
||||||
Request
|
Request
|
||||||
.B emp_server
|
.B emp_server
|
||||||
to reopen log files. This allows proper log rotation.
|
to reopen log files and reload its configuration. This allows proper
|
||||||
|
log rotation. Only the update schedule is reloaded at this time.
|
||||||
.TP
|
.TP
|
||||||
.BR SIGINT ", " SIGTERM
|
.BR SIGINT ", " SIGTERM
|
||||||
Request
|
Request
|
||||||
|
|
|
@ -49,12 +49,7 @@ force(void)
|
||||||
pr("Updates are disabled\n");
|
pr("Updates are disabled\n");
|
||||||
return RET_FAIL;
|
return RET_FAIL;
|
||||||
}
|
}
|
||||||
seconds = onearg(player->argp[1], "Time until update [in seconds]? ");
|
if (update_trigger() < 0)
|
||||||
if (seconds < 0)
|
|
||||||
return RET_FAIL;
|
|
||||||
|
|
||||||
pr("Scheduling update in %d second(s)\n", seconds);
|
|
||||||
if (update_trigger(seconds) < 0)
|
|
||||||
return RET_FAIL;
|
return RET_FAIL;
|
||||||
return RET_OK;
|
return RET_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
* upda.c: Give the time of the next update
|
* upda.c: Give the time of the next update
|
||||||
*
|
*
|
||||||
* Known contributors to this file:
|
* Known contributors to this file:
|
||||||
*
|
* Markus Armbruster, 2007
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
@ -36,7 +36,6 @@
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
#include "optlist.h"
|
#include "optlist.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "wantupd.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tell what the update policy is, and when the next update
|
* Tell what the update policy is, and when the next update
|
||||||
|
@ -47,7 +46,7 @@ upda(void)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
struct mob_acc_globals timestamps;
|
struct mob_acc_globals timestamps;
|
||||||
time_t now, next, delta;
|
time_t now, next, stop;
|
||||||
|
|
||||||
if (opt_MOB_ACCESS) {
|
if (opt_MOB_ACCESS) {
|
||||||
if ((fp = fopen(timestampfil, "rb")) == NULL)
|
if ((fp = fopen(timestampfil, "rb")) == NULL)
|
||||||
|
@ -70,66 +69,41 @@ upda(void)
|
||||||
pr("UPDATES ARE DISABLED!\n");
|
pr("UPDATES ARE DISABLED!\n");
|
||||||
|
|
||||||
(void)time(&now);
|
(void)time(&now);
|
||||||
switch (update_policy) {
|
next = update_time[0];
|
||||||
case UDP_NORMAL:
|
if (next) {
|
||||||
next_update_time(&now, &next, &delta);
|
|
||||||
pr("\nUpdates occur at times specified by the ETU rates.\n\n");
|
pr("\nUpdates occur at times specified by the ETU rates.\n\n");
|
||||||
pr("The next update is at %19.19s.\n", ctime(&next));
|
pr("The next update is at %19.19s.\n", ctime(&next));
|
||||||
break;
|
} else {
|
||||||
case UDP_TIMES:
|
|
||||||
next_update_time(&now, &next, &delta);
|
|
||||||
pr("\nUpdates occur at scheduled times.\n\n");
|
|
||||||
pr("The next update is at %19.19s.\n", ctime(&next));
|
|
||||||
break;
|
|
||||||
case UDP_BLITZ:
|
|
||||||
next_update_time(&now, &next, &delta);
|
|
||||||
pr("\nBlitz Updates occur every %d minutes. \n\n", blitz_time);
|
|
||||||
pr("The next update is at %19.19s.\n", ctime(&next));
|
|
||||||
break;
|
|
||||||
case UDP_NOREG:
|
|
||||||
pr("There are no regularly scheduled updates.\n");
|
pr("There are no regularly scheduled updates.\n");
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pr("Update policy is inconsistent.\n");
|
|
||||||
}
|
}
|
||||||
pr("The current time is %19.19s.\n\n", ctime(&now));
|
pr("The current time is %19.19s.\n\n", ctime(&now));
|
||||||
|
|
||||||
if (update_window) {
|
if (next && update_window) {
|
||||||
now = update_time - update_window;
|
|
||||||
next_update_time(&now, &next, &delta);
|
|
||||||
pr("The next update window starts at %19.19s.\n",
|
pr("The next update window starts at %19.19s.\n",
|
||||||
ctime(&next));
|
ctime(&next));
|
||||||
next += update_window;
|
stop = next + update_window;
|
||||||
pr("The next update window stops at %19.19s.\n", ctime(&next));
|
pr("The next update window stops at %19.19s.\n", ctime(&stop));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (update_demandpolicy) {
|
switch (update_demand) {
|
||||||
case UDDEM_TMCHECK:
|
case UPD_DEMAND_NONE:
|
||||||
next_update_check_time(&now, &next, &delta);
|
|
||||||
pr("Demand updates occur at update CHECK times.\n");
|
|
||||||
pr("The next update check is at %19.19s.\n",
|
|
||||||
ctime(&next));
|
|
||||||
break;
|
|
||||||
case UDDEM_COMSET:
|
|
||||||
pr("Demand updates occur right after the demand is set.\n");
|
|
||||||
break;
|
|
||||||
case UDDEM_DISABLE:
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
CANT_REACH();
|
break;
|
||||||
pr("Update demand policy is inconsistent.\n");
|
case UPD_DEMAND_SCHED:
|
||||||
}
|
pr("Demand updates occur at update CHECK times.\n");
|
||||||
|
if (next) {
|
||||||
if ((update_policy == UDP_TIMES) ||
|
pr("The next update check is at %19.19s.\n",
|
||||||
(update_demandpolicy == UDDEM_TMCHECK)) {
|
ctime(&next));
|
||||||
if (*update_times != 0)
|
}
|
||||||
pr("The update schedule is: %s\n", update_times);
|
pr("Demand updates require %d country(s) to want one.\n",
|
||||||
}
|
update_wantmin);
|
||||||
|
break;
|
||||||
if (update_demandpolicy != UDDEM_DISABLE) {
|
case UPD_DEMAND_ASYNC:
|
||||||
if (*update_demandtimes != 0)
|
pr("Demand updates occur right after the demand is set.\n");
|
||||||
|
if (*update_demandtimes != 0) {
|
||||||
pr("Demand updates are allowed during: %s\n",
|
pr("Demand updates are allowed during: %s\n",
|
||||||
update_demandtimes);
|
update_demandtimes);
|
||||||
|
}
|
||||||
pr("Demand updates require %d country(s) to want one.\n",
|
pr("Demand updates require %d country(s) to want one.\n",
|
||||||
update_wantmin);
|
update_wantmin);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,6 @@
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
#include "optlist.h"
|
#include "optlist.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "wantupd.h"
|
|
||||||
|
|
||||||
int
|
int
|
||||||
zdon(void)
|
zdon(void)
|
||||||
|
@ -70,7 +69,8 @@ zdon(void)
|
||||||
int dowant;
|
int dowant;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
|
||||||
if (update_demandpolicy == UDDEM_DISABLE) {
|
if (update_demand != UPD_DEMAND_SCHED
|
||||||
|
&& update_demand != UPD_DEMAND_ASYNC) {
|
||||||
pr("Demand updates are not enabled.\n");
|
pr("Demand updates are not enabled.\n");
|
||||||
return RET_FAIL;
|
return RET_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ zdon(void)
|
||||||
|
|
||||||
if (!checking && wantupd && demandupdatecheck()) {
|
if (!checking && wantupd && demandupdatecheck()) {
|
||||||
pr("Here goes...\n");
|
pr("Here goes...\n");
|
||||||
update_trigger(0);
|
update_trigger();
|
||||||
}
|
}
|
||||||
return RET_OK;
|
return RET_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,50 +101,6 @@ gamehours(time_t t)
|
||||||
return is_daytime_allowed(60 * tm->tm_hour + tm->tm_min, game_hours);
|
return is_daytime_allowed(60 * tm->tm_hour + tm->tm_min, game_hours);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Is day time DTIME (minutes since midnight) near a time in TIMES?
|
|
||||||
* TIMES is a list of day times. See daytime() for syntax.
|
|
||||||
* DTIME is near a listed time T if its within T and T + SLOP minutes.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
is_daytime_near(int dtime, char *times, int slop)
|
|
||||||
{
|
|
||||||
int dt;
|
|
||||||
|
|
||||||
if (times)
|
|
||||||
while (NULL != (times = daytime(times, &dt)))
|
|
||||||
if (dt <= dtime && dtime < dt + slop)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return time in minutes between DTIME and next time in TIMES.
|
|
||||||
* If TIMES doesn't give a time, return -1.
|
|
||||||
* DTIME is day time in minutes since midnight.
|
|
||||||
* TIMES is a list of day times. See daytime() for syntax.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
min_to_next_daytime(int dtime, char *times)
|
|
||||||
{
|
|
||||||
int mindt = INT_MAX;
|
|
||||||
int dt;
|
|
||||||
|
|
||||||
if (times) {
|
|
||||||
while (NULL != (times = daytime(times, &dt))) {
|
|
||||||
if (dt <= dtime)
|
|
||||||
dt += 24 * 60; /* tomorrow */
|
|
||||||
if (dt < mindt)
|
|
||||||
mindt = dt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mindt == INT_MAX)
|
|
||||||
return -1;
|
|
||||||
return mindt - dtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse weekday name in STR.
|
* Parse weekday name in STR.
|
||||||
* On success assign day number (Sunday is 0) to *WDAY and return
|
* On success assign day number (Sunday is 0) to *WDAY and return
|
||||||
|
|
320
src/lib/common/rdsched.c
Normal file
320
src/lib/common/rdsched.c
Normal file
|
@ -0,0 +1,320 @@
|
||||||
|
/*
|
||||||
|
* Empire - A multi-player, client/server Internet based war game.
|
||||||
|
* Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
|
||||||
|
* Ken Stevens, Steve McClure
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
* See files README, COPYING and CREDITS in the root of the source
|
||||||
|
* tree for related information and legal notices. It is expected
|
||||||
|
* that future projects/authors will amend these files as needed.
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
* rdsched.c: Read update schedule
|
||||||
|
*
|
||||||
|
* Known contributors to this file:
|
||||||
|
* Markus Armbruster, 2007
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _XOPEN_SOURCE 500
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include "prototypes.h"
|
||||||
|
|
||||||
|
static int parse_schedule_line(char *, time_t[], int, time_t, time_t *,
|
||||||
|
char *, int);
|
||||||
|
static int time_ok(time_t, char *, int);
|
||||||
|
static char *parse_time(time_t *, char *, time_t *);
|
||||||
|
static char *parse_every(time_t *, char *);
|
||||||
|
static char *parse_until(time_t *, char *, time_t *);
|
||||||
|
static char *parse_skip(time_t *, char *, time_t *);
|
||||||
|
static int insert_update(time_t, time_t[], int, time_t);
|
||||||
|
static int delete_update(time_t, time_t[], int);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read update schedule from file FNAME.
|
||||||
|
* Put the first N-1 updates after T0 into SCHED[] in ascending order,
|
||||||
|
* terminated with a zero.
|
||||||
|
* Use ANCHOR as initial anchor for anchor-relative times.
|
||||||
|
* Return 0 on success, -1 on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
read_schedule(char *fname, time_t sched[], int n, time_t t0, time_t anchor)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
int lno = 0;
|
||||||
|
char buf[1024];
|
||||||
|
char *endp;
|
||||||
|
|
||||||
|
if (fname) {
|
||||||
|
fp = fopen(fname, "r");
|
||||||
|
if (!fp) {
|
||||||
|
logerror("Can't open %s for reading (%s)\n",
|
||||||
|
fname, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fp = stdin;
|
||||||
|
fname = "<stdin>";
|
||||||
|
}
|
||||||
|
|
||||||
|
sched[0] = 0;
|
||||||
|
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||||
|
++lno;
|
||||||
|
endp = strchr(buf, '#');
|
||||||
|
if (endp)
|
||||||
|
*endp = 0;
|
||||||
|
if (parse_schedule_line(buf, sched, n, t0, &anchor, fname, lno))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse an update schedule directive from LINE.
|
||||||
|
* Update SCHED[] and ANCHOR accordingly.
|
||||||
|
* SCHED[] holds the first N-1 updates after T0 in ascending order.
|
||||||
|
* FNAME and LNO file name and line number for reporting errors.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
parse_schedule_line(char *line, time_t sched[], int n,
|
||||||
|
time_t t0, time_t *anchor,
|
||||||
|
char *fname, int lno)
|
||||||
|
{
|
||||||
|
char *endp, *p;
|
||||||
|
int bol;
|
||||||
|
time_t t, delta, u;
|
||||||
|
|
||||||
|
if ((endp = parse_time(&t, line, anchor))) {
|
||||||
|
if (!time_ok(t, fname, lno))
|
||||||
|
return -1;
|
||||||
|
*anchor = t;
|
||||||
|
insert_update(t, sched, n, t0);
|
||||||
|
} else if ((endp = parse_every(&delta, line))) {
|
||||||
|
if ((p = parse_until(&u, endp, anchor))) {
|
||||||
|
endp = p;
|
||||||
|
if (!time_ok(u, fname, lno))
|
||||||
|
return -1;
|
||||||
|
} else
|
||||||
|
u = (time_t)-1;
|
||||||
|
t = *anchor;
|
||||||
|
do {
|
||||||
|
t += delta;
|
||||||
|
} while ((u == (time_t)-1 || t <= u)
|
||||||
|
&& insert_update(t, sched, n, t0) < n - 1);
|
||||||
|
} else if ((endp = parse_skip(&t, line, anchor))) {
|
||||||
|
if (!time_ok(t, fname, lno))
|
||||||
|
return -1;
|
||||||
|
delete_update(t, sched, n);
|
||||||
|
} else
|
||||||
|
endp = line;
|
||||||
|
|
||||||
|
bol = endp == line;
|
||||||
|
while (isspace(*endp)) endp++;
|
||||||
|
if (*endp) {
|
||||||
|
if (bol)
|
||||||
|
logerror("%s:%d: unintelligible\n", fname, lno);
|
||||||
|
else
|
||||||
|
logerror("%s:%d: trailing junk\n", fname, lno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Complain and return zero when T is bad, else return non-zero.
|
||||||
|
* FNAME and LNO file name and line number.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
time_ok(time_t t, char *fname, int lno)
|
||||||
|
{
|
||||||
|
if (t == (time_t)-1) {
|
||||||
|
logerror("%s:%d: time weird\n", fname, lno);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse a time from S into *T.
|
||||||
|
* *ANCHOR is the base for anchor-relative time.
|
||||||
|
* Return pointer to first character not parsed on success,
|
||||||
|
* null pointer on failure.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
parse_time(time_t *t, char *s, time_t *anchor)
|
||||||
|
{
|
||||||
|
static char *fmt[] = {
|
||||||
|
"%Y-%m-%d %H:%M ", /* ISO 8601 */
|
||||||
|
"%b %d %H:%M %Y ", /* like ctime(): Dec 22 15:35 2006 */
|
||||||
|
"%d %b %Y %H:%M ", /* 22 Dec 2006 15:35 */
|
||||||
|
"next %a %H:%M ", /* next Fri 15:35 */
|
||||||
|
"next %a ", /* next Fri */
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
char *p, *endp;
|
||||||
|
int i;
|
||||||
|
struct tm tm, nexttm;
|
||||||
|
|
||||||
|
for (p = s; isspace(*(unsigned char *)p); ++p) ;
|
||||||
|
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
if (!fmt[i])
|
||||||
|
return NULL;
|
||||||
|
memset(&tm, 0, sizeof(tm));
|
||||||
|
tm.tm_hour = -1;
|
||||||
|
endp = strptime(p, fmt[i], &tm);
|
||||||
|
if (endp)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tm.tm_mday == 0) {
|
||||||
|
/* relative to anchor */
|
||||||
|
nexttm = *localtime(anchor);
|
||||||
|
if (tm.tm_hour >= 0) {
|
||||||
|
/* got hour and minute */
|
||||||
|
nexttm.tm_hour = tm.tm_hour;
|
||||||
|
nexttm.tm_min = tm.tm_min;
|
||||||
|
nexttm.tm_sec = 0;
|
||||||
|
}
|
||||||
|
nexttm.tm_mday += tm.tm_wday - nexttm.tm_wday;
|
||||||
|
if (tm.tm_wday <= nexttm.tm_wday)
|
||||||
|
nexttm.tm_mday += 7;
|
||||||
|
tm = nexttm;
|
||||||
|
}
|
||||||
|
|
||||||
|
*t = mktime(&tm);
|
||||||
|
return endp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse an every clause from S into *SECS.
|
||||||
|
* Return pointer to first character not parsed on success,
|
||||||
|
* null pointer on failure.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
parse_every(time_t *secs, char *s)
|
||||||
|
{
|
||||||
|
int nch, delta;
|
||||||
|
|
||||||
|
nch = -1;
|
||||||
|
sscanf(s, " every %u hours%n", &delta, &nch);
|
||||||
|
if (nch >= 0)
|
||||||
|
delta *= 60;
|
||||||
|
else
|
||||||
|
sscanf(s, " every %u minutes%n", &delta, &nch);
|
||||||
|
if (nch < 0)
|
||||||
|
return NULL; *secs = 60 * delta;
|
||||||
|
return s + nch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse an until clause from S into *T.
|
||||||
|
* *ANCHOR is the base for anchor-relative time.
|
||||||
|
* Return pointer to first character not parsed on success,
|
||||||
|
* null pointer on failure.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
parse_until(time_t *t, char *s, time_t *anchor)
|
||||||
|
{
|
||||||
|
int nch;
|
||||||
|
|
||||||
|
nch = -1;
|
||||||
|
sscanf(s, " until%n", &nch);
|
||||||
|
if (nch < 0)
|
||||||
|
return NULL;
|
||||||
|
return parse_time(t, s + nch, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse an skip clause from S into *T.
|
||||||
|
* *ANCHOR is the base for anchor-relative time.
|
||||||
|
* Return pointer to first character not parsed on success,
|
||||||
|
* null pointer on failure.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
parse_skip(time_t *t, char *s, time_t *anchor)
|
||||||
|
{
|
||||||
|
int nch;
|
||||||
|
|
||||||
|
nch = -1;
|
||||||
|
sscanf(s, " skip%n", &nch);
|
||||||
|
if (nch < 0)
|
||||||
|
return NULL;
|
||||||
|
return parse_time(t, s + nch, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the index of the first update at or after T in SCHED[].
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
find_update(time_t t, time_t sched[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Could use binary search here, but it's hardly worth it */
|
||||||
|
for (i = 0; sched[i] && t > sched[i]; i++) ;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert update at T into SCHED[].
|
||||||
|
* SCHED[] holds the first N-1 updates after T0 in ascending order.
|
||||||
|
* If T is before T0 or outside game_days/game_hours, return -1.
|
||||||
|
* If there's no space for T in SCHED[], return N-1.
|
||||||
|
* Else insert T into SCHED[] and return its index in SCHED[].
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
insert_update(time_t t, time_t sched[], int n, time_t t0)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (t <= t0 || !gamehours(t))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
i = find_update(t, sched);
|
||||||
|
memmove(sched + i + 1, sched + i, (n - 1 - i) * sizeof(*sched));
|
||||||
|
sched[i] = t;
|
||||||
|
sched[n - 1] = 0;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete update T from SCHED[].
|
||||||
|
* SCHED[] holds N-1 updates in ascending order.
|
||||||
|
* Return the index of the first update after T in SCHED[].
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
delete_update(time_t t, time_t sched[], int n)
|
||||||
|
{
|
||||||
|
int i = find_update(t, sched);
|
||||||
|
if (t == sched[i])
|
||||||
|
memmove(sched + i, sched + i + 1,
|
||||||
|
(n - 1 - i) * sizeof(*sched));
|
||||||
|
return i;
|
||||||
|
}
|
|
@ -47,26 +47,6 @@
|
||||||
#include "nat.h"
|
#include "nat.h"
|
||||||
#include "optlist.h"
|
#include "optlist.h"
|
||||||
#include "prototypes.h"
|
#include "prototypes.h"
|
||||||
#include "wantupd.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
update_policy_check(void)
|
|
||||||
{
|
|
||||||
if (update_policy < 0)
|
|
||||||
update_policy = UDP_DEFAULT;
|
|
||||||
if (update_policy > UDP_MAX)
|
|
||||||
update_policy = UDP_DEFAULT;
|
|
||||||
if (update_demandpolicy < 0)
|
|
||||||
update_demandpolicy = UDDEM_DEFAULT;
|
|
||||||
if (update_demandpolicy > UDDEM_MAX)
|
|
||||||
update_demandpolicy = UDDEM_DEFAULT;
|
|
||||||
if (update_wantmin < 1)
|
|
||||||
update_wantmin = 1;
|
|
||||||
if (update_wantmin > MAXNOC)
|
|
||||||
update_wantmin = MAXNOC;
|
|
||||||
if (blitz_time < 1)
|
|
||||||
blitz_time = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
demand_update_time(time_t *now)
|
demand_update_time(time_t *now)
|
||||||
|
@ -78,45 +58,6 @@ demand_update_time(time_t *now)
|
||||||
update_demandtimes);
|
update_demandtimes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When is the next regularly scheduled update from now. */
|
|
||||||
static void
|
|
||||||
regular_update_time(time_t *now, time_t *tim, time_t *delta)
|
|
||||||
{
|
|
||||||
time_t tw;
|
|
||||||
int secs_per_update;
|
|
||||||
|
|
||||||
tw = *now + adj_update;
|
|
||||||
secs_per_update = etu_per_update * s_p_etu;
|
|
||||||
*delta = secs_per_update - (tw % secs_per_update);
|
|
||||||
*tim = *now + *delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Is this a valid time for a scheduled update. */
|
|
||||||
static int
|
|
||||||
scheduled_update_time(time_t *now)
|
|
||||||
{
|
|
||||||
struct tm *tm;
|
|
||||||
|
|
||||||
tm = localtime(now);
|
|
||||||
return is_daytime_near(60 * tm->tm_hour + tm->tm_min,
|
|
||||||
update_times, hourslop);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
next_scheduled_time(time_t *now, time_t *tim, time_t *delta)
|
|
||||||
{
|
|
||||||
struct tm *tm;
|
|
||||||
int d;
|
|
||||||
|
|
||||||
tm = localtime(now);
|
|
||||||
d = min_to_next_daytime(60 * tm->tm_hour + tm->tm_min, update_times);
|
|
||||||
if (d < 0)
|
|
||||||
return 0;
|
|
||||||
*delta = 60 * d;
|
|
||||||
*tim = *now + *delta - tm->tm_sec;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
demand_update_want(int *want, int *pop, int which)
|
demand_update_want(int *want, int *pop, int which)
|
||||||
{
|
{
|
||||||
|
@ -144,12 +85,14 @@ demand_update_want(int *want, int *pop, int which)
|
||||||
return whichwants;
|
return whichwants;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
/*
|
||||||
|
* Do we have sufficient votes for a demand update?
|
||||||
|
*/
|
||||||
|
int
|
||||||
demand_check(void)
|
demand_check(void)
|
||||||
{
|
{
|
||||||
struct natstr *natp;
|
struct natstr *natp;
|
||||||
int want, pop, cn, veto;
|
int want, pop, cn, veto;
|
||||||
time_t now;
|
|
||||||
|
|
||||||
demand_update_want(&want, &pop, 0);
|
demand_update_want(&want, &pop, 0);
|
||||||
if (want < update_wantmin) {
|
if (want < update_wantmin) {
|
||||||
|
@ -158,13 +101,6 @@ demand_check(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
time(&now);
|
|
||||||
if (!demand_update_time(&now)) {
|
|
||||||
logerror("no demand update, not within hours allowed.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
veto = 0;
|
veto = 0;
|
||||||
for (cn = 1; 0 != (natp = getnatp(cn)); cn++) {
|
for (cn = 1; 0 != (natp = getnatp(cn)); cn++) {
|
||||||
if (natp->nat_stat == STAT_ACTIVE) {
|
if (natp->nat_stat == STAT_ACTIVE) {
|
||||||
|
@ -183,118 +119,17 @@ demand_check(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if enough countries want an update,
|
* Can we have an unscheduled demand update now?
|
||||||
* and if demand updates are allowed now.
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
demandupdatecheck(void)
|
demandupdatecheck(void)
|
||||||
{
|
{
|
||||||
if (UDDEM_COMSET != update_demandpolicy) {
|
time_t now = time(NULL);
|
||||||
logerror("no demand update, not policy.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return demand_check();
|
return update_demand == UPD_DEMAND_ASYNC
|
||||||
}
|
&& !updates_disabled()
|
||||||
|
&& demand_update_time(&now)
|
||||||
/*
|
&& demand_check();
|
||||||
* Is it time for a regular or scheduled update?
|
|
||||||
* As well, if none of the above, check to see if
|
|
||||||
* a demand update can occur.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
updatetime(time_t *now)
|
|
||||||
{
|
|
||||||
if (opt_BLITZ && update_policy == UDP_BLITZ) {
|
|
||||||
logerror("BLITZ Update.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UDP_NORMAL == update_policy) {
|
|
||||||
logerror("Regular update, etu type.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UDP_TIMES == update_policy) {
|
|
||||||
if (scheduled_update_time(now)) {
|
|
||||||
logerror("Scheduled update.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (UDDEM_DISABLE != update_demandpolicy) {
|
|
||||||
if (demand_check()) {
|
|
||||||
logerror("Demand update, at check time.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the time, and delta seconds, of the next update.
|
|
||||||
* If the policy is no regular updates, return the time of
|
|
||||||
* the next possible check.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
next_update_time(time_t *now, time_t *tim, time_t *delta)
|
|
||||||
/* From when */
|
|
||||||
/* Time of next update */
|
|
||||||
/* Seconds till next update */
|
|
||||||
{
|
|
||||||
time_t stim, sdelta;
|
|
||||||
|
|
||||||
switch (update_policy) {
|
|
||||||
case UDP_NORMAL:
|
|
||||||
regular_update_time(now, tim, delta);
|
|
||||||
break;
|
|
||||||
case UDP_TIMES:
|
|
||||||
if (!next_scheduled_time(now, tim, delta))
|
|
||||||
regular_update_time(now, tim, delta);
|
|
||||||
break;
|
|
||||||
case UDP_BLITZ:
|
|
||||||
*delta = (blitz_time * 60) - (*now % (blitz_time * 60));
|
|
||||||
*tim = *now + *delta;
|
|
||||||
break;
|
|
||||||
case UDP_NOREG:
|
|
||||||
default:
|
|
||||||
regular_update_time(now, tim, delta);
|
|
||||||
if (next_scheduled_time(now, &stim, &sdelta)) {
|
|
||||||
if (*delta > sdelta) {
|
|
||||||
*delta = sdelta;
|
|
||||||
*tim = stim;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
next_update_check_time(time_t *now, time_t *tim, time_t *delta)
|
|
||||||
/* From when */
|
|
||||||
/* Time of next update */
|
|
||||||
/* Seconds till next update check */
|
|
||||||
{
|
|
||||||
time_t stim, sdelta;
|
|
||||||
|
|
||||||
switch (update_policy) {
|
|
||||||
case UDP_NORMAL:
|
|
||||||
regular_update_time(now, tim, delta);
|
|
||||||
break;
|
|
||||||
case UDP_BLITZ:
|
|
||||||
*delta = (blitz_time * 60) - (*now % (blitz_time * 60));
|
|
||||||
*tim = *now + *delta;
|
|
||||||
break;
|
|
||||||
case UDP_TIMES:
|
|
||||||
case UDP_NOREG:
|
|
||||||
default:
|
|
||||||
regular_update_time(now, tim, delta);
|
|
||||||
if (next_scheduled_time(now, &stim, &sdelta)) {
|
|
||||||
if (*delta > sdelta) {
|
|
||||||
*delta = sdelta;
|
|
||||||
*tim = stim;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -70,7 +70,7 @@ struct keymatch configkeys[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct keymatch *keylookup(char *key, struct keymatch tbl[]);
|
static struct keymatch *keylookup(char *key, struct keymatch tbl[]);
|
||||||
static void set_dirs(char *);
|
static void set_paths(char *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* read in empire configuration
|
* read in empire configuration
|
||||||
|
@ -154,7 +154,7 @@ emp_config(char *file)
|
||||||
|
|
||||||
done:
|
done:
|
||||||
WORLD_X &= ~1; /* force even */
|
WORLD_X &= ~1; /* force even */
|
||||||
set_dirs(file);
|
set_paths(file);
|
||||||
|
|
||||||
return -errors;
|
return -errors;
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ keylookup(char *command, struct keymatch *tbl)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_dirs(char *econfig)
|
set_paths(char *econfig)
|
||||||
{
|
{
|
||||||
char *slash;
|
char *slash;
|
||||||
char *cwd = getcwd(NULL, 0);
|
char *cwd = getcwd(NULL, 0);
|
||||||
|
@ -204,6 +204,9 @@ set_dirs(char *econfig)
|
||||||
}
|
}
|
||||||
#endif /* !_WIN32 */
|
#endif /* !_WIN32 */
|
||||||
|
|
||||||
|
schedulefil = malloc(strlen(configdir) + 10);
|
||||||
|
sprintf(schedulefil, "%s/schedule", configdir);
|
||||||
|
|
||||||
free(cwd);
|
free(cwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include "wantupd.h"
|
#include "optlist.h"
|
||||||
|
|
||||||
/* Name of the deity */
|
/* Name of the deity */
|
||||||
char *privname = "Deity forgot to edit econfig";
|
char *privname = "Deity forgot to edit econfig";
|
||||||
|
@ -56,15 +56,10 @@ int TRADE_DELAY = 7200; /* Seconds to bid on units */
|
||||||
int m_m_p_d = 1440; /* max mins of play per day (per country) */
|
int m_m_p_d = 1440; /* max mins of play per day (per country) */
|
||||||
int s_p_etu = 10; /* seconds per Empire Time Unit */
|
int s_p_etu = 10; /* seconds per Empire Time Unit */
|
||||||
int etu_per_update = 60; /* # of etu's per update */
|
int etu_per_update = 60; /* # of etu's per update */
|
||||||
int adj_update = 0; /* update time adjustment, in seconds */
|
|
||||||
int update_window = 0; /* update window adjustment, in seconds */
|
int update_window = 0; /* update window adjustment, in seconds */
|
||||||
int hourslop = 5; /* update_times matching fuzz, in minutes */
|
int update_demand = UPD_DEMAND_NONE;
|
||||||
char *update_times = ""; /* update times for policy UDP_TIMES */
|
|
||||||
int update_policy = UDP_DEFAULT; /* update policy for regular updates */
|
|
||||||
int update_demandpolicy = UDDEM_DEFAULT; /* update policy for demand updates */
|
|
||||||
int update_missed = 999; /* demand updates missed before veto */
|
int update_missed = 999; /* demand updates missed before veto */
|
||||||
int update_wantmin = 1; /* votes required for demand update */
|
int update_wantmin = 1; /* votes required for demand update */
|
||||||
int blitz_time = 10; /* number of minutes between blitz updates */
|
|
||||||
char *update_demandtimes = ""; /* demand update time ranges */
|
char *update_demandtimes = ""; /* demand update time ranges */
|
||||||
char *game_days = ""; /* days game is running */
|
char *game_days = ""; /* days game is running */
|
||||||
char *game_hours = ""; /* hours game is running */
|
char *game_hours = ""; /* hours game is running */
|
||||||
|
|
|
@ -49,6 +49,9 @@ char *configdir;
|
||||||
/* User configuration tables to load (relative to configdir) */
|
/* User configuration tables to load (relative to configdir) */
|
||||||
char *custom_tables = "";
|
char *custom_tables = "";
|
||||||
|
|
||||||
|
/* Update schedule (absolute file name) */
|
||||||
|
char *schedulefil;
|
||||||
|
|
||||||
/* Where to find built-in configuration tables (relative to configdir) */
|
/* Where to find built-in configuration tables (relative to configdir) */
|
||||||
char *builtindir = "@builtindir@";
|
char *builtindir = "@builtindir@";
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ struct cmndstr player_coms[] = {
|
||||||
{"fly <cargo-PLANES> <fighter-PLANES> <ap-SECT> <PATH|DESTINATION> <COM>",
|
{"fly <cargo-PLANES> <fighter-PLANES> <ap-SECT> <PATH|DESTINATION> <COM>",
|
||||||
2, fly, C_MOD, NORM + MONEY + CAP},
|
2, fly, C_MOD, NORM + MONEY + CAP},
|
||||||
{"follow <leader> <SHIPS>", 1, foll, C_MOD, NORM + CAP},
|
{"follow <leader> <SHIPS>", 1, foll, C_MOD, NORM + CAP},
|
||||||
{"force <delay time>", 0, force, C_MOD, GOD},
|
{"force", 0, force, C_MOD, GOD},
|
||||||
{"fortify <UNITS> <MOB>", 1, fort, C_MOD, NORM},
|
{"fortify <UNITS> <MOB>", 1, fort, C_MOD, NORM},
|
||||||
{"fuel <s|l> <SHIP/FLEET | UNIT/ARMY> <AMOUNT> [<OILER>]",
|
{"fuel <s|l> <SHIP/FLEET | UNIT/ARMY> <AMOUNT> [<OILER>]",
|
||||||
1, fuel, C_MOD, NORM},
|
1, fuel, C_MOD, NORM},
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "update.h"
|
#include "update.h"
|
||||||
#include "wantupd.h"
|
|
||||||
|
|
||||||
long money[MAXNOC];
|
long money[MAXNOC];
|
||||||
long pops[MAXNOC];
|
long pops[MAXNOC];
|
||||||
|
@ -159,7 +158,8 @@ update_main(void)
|
||||||
mob_plane(etu);
|
mob_plane(etu);
|
||||||
mob_land(etu);
|
mob_land(etu);
|
||||||
}
|
}
|
||||||
if (update_demandpolicy != UDDEM_DISABLE)
|
if (update_demand == UPD_DEMAND_SCHED
|
||||||
|
|| update_demand == UPD_DEMAND_ASYNC)
|
||||||
update_removewants();
|
update_removewants();
|
||||||
/* flush all mem file objects to disk */
|
/* flush all mem file objects to disk */
|
||||||
ef_flush(EF_NATION);
|
ef_flush(EF_NATION);
|
||||||
|
|
|
@ -267,6 +267,7 @@ main(int argc, char **argv)
|
||||||
#ifdef SIGHUP
|
#ifdef SIGHUP
|
||||||
if (sig == SIGHUP) {
|
if (sig == SIGHUP) {
|
||||||
journal_reopen();
|
journal_reopen();
|
||||||
|
update_reschedule();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -290,7 +291,6 @@ init_server(void)
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
loc_NTInit();
|
loc_NTInit();
|
||||||
#endif
|
#endif
|
||||||
update_policy_check();
|
|
||||||
player_init();
|
player_init();
|
||||||
ef_init_srv();
|
ef_init_srv();
|
||||||
io_init();
|
io_init();
|
||||||
|
|
|
@ -48,14 +48,18 @@
|
||||||
#include "prototypes.h"
|
#include "prototypes.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
static empth_t *update_thread;
|
#define UPDATES 16
|
||||||
empth_rwlock_t *update_lock;
|
|
||||||
int update_pending;
|
|
||||||
time_t update_time;
|
|
||||||
static int update_forced;
|
|
||||||
|
|
||||||
|
empth_rwlock_t *update_lock;
|
||||||
|
static empth_t *update_thread;
|
||||||
|
int update_pending;
|
||||||
|
|
||||||
|
time_t update_time[UPDATES];
|
||||||
|
static time_t update_schedule_anchor;
|
||||||
|
static int update_wanted;
|
||||||
|
|
||||||
|
static int update_get_schedule(void);
|
||||||
static void update_sched(void *);
|
static void update_sched(void *);
|
||||||
static void update_force(void *);
|
|
||||||
static void update_run(void);
|
static void update_run(void);
|
||||||
static int run_hook(char *cmd, char *name);
|
static int run_hook(char *cmd, char *name);
|
||||||
|
|
||||||
|
@ -71,6 +75,10 @@ update_init(void)
|
||||||
logerror("setting s_p_etu to %d", s_p_etu);
|
logerror("setting s_p_etu to %d", s_p_etu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_schedule_anchor = (time(NULL) + 59) / 60 * 60;
|
||||||
|
if (update_get_schedule() < 0)
|
||||||
|
exit(1);
|
||||||
|
|
||||||
update_lock = empth_rwlock_create("Update");
|
update_lock = empth_rwlock_create("Update");
|
||||||
if (!update_lock)
|
if (!update_lock)
|
||||||
exit_nomem();
|
exit_nomem();
|
||||||
|
@ -88,91 +96,100 @@ update_init(void)
|
||||||
exit_nomem();
|
exit_nomem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the schedule for future updates into update_time[].
|
||||||
|
* Return 0 on success, -1 on failure.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
update_get_schedule(void)
|
||||||
|
{
|
||||||
|
time_t now = time(NULL);
|
||||||
|
|
||||||
|
if (read_schedule(schedulefil, update_time, UPDATES,
|
||||||
|
now + 30, update_schedule_anchor) < 0) {
|
||||||
|
logerror("No update schedule!");
|
||||||
|
update_time[0] = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
logerror("Update schedule read");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
static void
|
static void
|
||||||
update_sched(void *unused)
|
update_sched(void *unused)
|
||||||
{
|
{
|
||||||
int wind;
|
time_t next_update, now;
|
||||||
time_t now, delta;
|
|
||||||
|
|
||||||
player->proc = empth_self();
|
player->proc = empth_self();
|
||||||
player->cnum = 0;
|
player->cnum = 0;
|
||||||
player->god = 1;
|
player->god = 1;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
time(&now);
|
/*
|
||||||
next_update_time(&now, &update_time, &delta);
|
* Sleep until the next scheduled update or an unscheduled
|
||||||
if (update_window > 0) {
|
* wakeup.
|
||||||
wind = (random() % update_window);
|
*/
|
||||||
update_time += wind;
|
next_update = update_time[0];
|
||||||
delta += wind;
|
if (next_update) {
|
||||||
|
if (update_window > 0)
|
||||||
|
next_update += random() % update_window;
|
||||||
|
logerror("Next update at %s", ctime(&next_update));
|
||||||
|
/* sleep until update is scheduled to go off */
|
||||||
|
empth_sleep(next_update);
|
||||||
|
} else {
|
||||||
|
logerror("No update scheduled");
|
||||||
|
/* want to sleep forever, but empthread doesn't provide that */
|
||||||
|
while (empth_sleep(60 * 60 * 24) >= 0) ;
|
||||||
}
|
}
|
||||||
logerror("Next update at %s", ctime(&update_time));
|
|
||||||
logerror("Next update in %ld seconds", (long)delta);
|
now = time(NULL);
|
||||||
/* sleep until update is scheduled to go off */
|
if (next_update != 0 && now >= next_update) {
|
||||||
update_forced = 0;
|
/* scheduled update time reached */
|
||||||
empth_sleep(update_time);
|
if (now >= next_update + 60)
|
||||||
if (!update_forced) {
|
logerror("Missed the update!");
|
||||||
time(&now);
|
else if (update_demand == UPD_DEMAND_SCHED && !demand_check())
|
||||||
now += adj_update;
|
;
|
||||||
if (!gamehours(now)) {
|
else if (updates_disabled())
|
||||||
logerror("No update permitted (hours restriction)");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!updatetime(&now)) {
|
|
||||||
logerror("No update wanted");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (updates_disabled()) {
|
|
||||||
logerror("Updates disabled...skipping update");
|
logerror("Updates disabled...skipping update");
|
||||||
continue;
|
else
|
||||||
}
|
update_wanted = 1;
|
||||||
|
update_schedule_anchor = update_time[0];
|
||||||
}
|
}
|
||||||
update_run();
|
/* else unscheduled update if update_wanted is set */
|
||||||
|
|
||||||
|
if (update_wanted) {
|
||||||
|
update_wanted = 0;
|
||||||
|
update_run();
|
||||||
|
}
|
||||||
|
|
||||||
|
update_get_schedule();
|
||||||
}
|
}
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Trigger an update SECS_FROM_NOW seconds from now.
|
* Trigger an update.
|
||||||
* Return 0 on success, -1 on failure.
|
* Return 0 on success, -1 on failure.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
update_trigger(time_t secs_from_now)
|
update_trigger(void)
|
||||||
{
|
{
|
||||||
time_t *secp;
|
logerror("Triggering unscheduled update");
|
||||||
|
update_wanted = 1;
|
||||||
if (secs_from_now < 0)
|
empth_wakeup(update_thread);
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (secs_from_now == 0) {
|
|
||||||
update_forced = 1;
|
|
||||||
empth_wakeup(update_thread);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME make triggers overwrite, not accumulate */
|
|
||||||
secp = malloc(sizeof(time_t));
|
|
||||||
if (!secp)
|
|
||||||
return -1;
|
|
||||||
*secp = secs_from_now;
|
|
||||||
if (!empth_create(PP_SCHED, update_force, 50 * 1024, 0,
|
|
||||||
"forceUpdate", secp))
|
|
||||||
return -1;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/*
|
||||||
update_force(void *seconds)
|
* Reload the update schedule.
|
||||||
|
* Return 0 on success, -1 on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
update_reschedule(void)
|
||||||
{
|
{
|
||||||
time_t now;
|
|
||||||
|
|
||||||
time(&now);
|
|
||||||
empth_sleep(now + *(time_t *)seconds);
|
|
||||||
update_forced = 1;
|
|
||||||
empth_wakeup(update_thread);
|
empth_wakeup(update_thread);
|
||||||
free(seconds);
|
return 0;
|
||||||
empth_exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue