src/timer.c

Go to the documentation of this file.
00001 /*
00002  * timer.c -- Subroutines for (system-) timed events 
00003  */
00004 
00005 #include "copyright.h"
00006 #include "config.h"
00007 
00008 #include <signal.h>
00009 
00010 #include "mudconf.h"
00011 #include "config.h"
00012 #include "db.h"
00013 #include "interface.h"
00014 #include "match.h"
00015 #include "externs.h"
00016 #include "command.h"
00017 #include "attrs.h"
00018 #include "powers.h"
00019 
00020 extern void pool_reset(void);
00021 extern void do_second(void);
00022 extern void fork_and_dump(int key);
00023 extern unsigned int alarm(unsigned int seconds);
00024 extern void pcache_trim(void);
00025 void check_events(void);
00026 
00027 void timer_callback(int fd, short event, void *arg);
00028 
00029 static struct timeval tv = { 0, 100000 };
00030 static struct event timer_event;
00031 
00032 void init_timer()
00033 {
00034         mudstate.now = time(NULL);
00035         mudstate.dump_counter =
00036                 ((mudconf.dump_offset ==
00037                   0) ? mudconf.dump_interval : mudconf.dump_offset) + mudstate.now;
00038         mudstate.check_counter =
00039                 ((mudconf.check_offset ==
00040                   0) ? mudconf.check_interval : mudconf.check_offset) + mudstate.now;
00041         mudstate.idle_counter = mudconf.idle_interval + mudstate.now;
00042         mudstate.mstats_counter = 15 + mudstate.now;
00043         mudstate.events_counter = 900 + mudstate.now;
00044         evtimer_set(&timer_event, timer_callback, NULL);
00045         evtimer_add(&timer_event, &tv);
00046 }
00047 
00048 #undef DISPATCH_DEBUG
00049 
00050 #ifdef DISPATCH_DEBUG
00051 #define DPSET(n) mudstate.debug_cmd = (char *) n
00052 #else
00053 #define DPSET(n)
00054 #endif
00055 
00056 void check_idle(void)
00057 {
00058     DESC *d, *dnext;
00059     time_t idletime;
00060     
00061     DESC_SAFEITER_ALL(d, dnext) {
00062         if(d->flags & DS_CONNECTED) {
00063             idletime = mudstate.now - d->last_time;
00064             if((idletime > d->timeout) && !Can_Idle(d->player)) {
00065                 queue_string(d, "*** Inactivity Timeout ***\r\n");
00066                 shutdownsock(d, R_TIMEOUT);
00067             } else if(mudconf.idle_wiz_dark &&
00068                       (idletime > mudconf.idle_timeout) && Can_Idle(d->player)
00069                       && !Dark(d->player)) {
00070                 s_Flags(d->player, Flags(d->player) | DARK);
00071                 d->flags |= DS_AUTODARK;
00072             }   
00073         } else {
00074             idletime = mudstate.now - d->connected_at;
00075             if(idletime > mudconf.conn_timeout) {
00076                 queue_string(d, "*** Login Timeout ***\r\n");
00077                 shutdownsock(d, R_TIMEOUT);
00078             }   
00079         }   
00080     }   
00081 }   
00082 
00083 void check_events(void)
00084 {
00085     struct tm *ltime;
00086     dbref thing, parent;
00087     int lev;
00088     
00089     ltime = localtime(&mudstate.now);
00090     if((ltime->tm_hour == mudconf.events_daily_hour)
00091        && !(mudstate.events_flag & ET_DAILY)) {
00092         mudstate.events_flag = mudstate.events_flag | ET_DAILY;
00093         DO_WHOLE_DB(thing) { 
00094             if(Going(thing))
00095                 continue;
00096                 
00097             ITER_PARENTS(thing, parent, lev) {
00098                 if(Flags2(thing) & HAS_DAILY) {
00099                     did_it(Owner(thing), thing, 0, NULL, 0, NULL, A_DAILY,
00100                            (char **) NULL, 0);
00101                            
00102                     break;
00103                 }   
00104             }   
00105         }   
00106     }   
00107     if(ltime->tm_hour != mudstate.events_lasthour) {
00108         if(mudstate.events_lasthour >= 0) {
00109             /* Run hourly maintenance */
00110             DO_WHOLE_DB(thing) {
00111                 if(Going(thing))
00112                     continue;
00113                     
00114                 ITER_PARENTS(thing, parent, lev) {
00115                     if(Flags2(thing) & HAS_HOURLY) {
00116                         did_it(Owner(thing), thing, 0, NULL, 0, NULL,
00117                                A_HOURLY, (char **) NULL, 0); 
00118                                
00119                         break;
00120                     }   
00121                 }   
00122             }   
00123             
00124         }
00125         mudstate.events_lasthour = ltime->tm_hour;
00126     }
00127     if(ltime->tm_hour == 23) {  /*
00128                                  * Nightly resetting 
00129                                  */
00130         mudstate.events_flag = 0;
00131     }
00132 }
00133 
00134 
00135 void dispatch()
00136 {
00137         char *cmdsave;
00138 
00139 #ifdef USE_PYTHON
00140         mudstate.debug_cmd = "< Python >";
00141         updatePython();
00142 #endif
00143 
00144         cmdsave = mudstate.debug_cmd;
00145         DPSET("< dispatch >");
00146         /*
00147          * this routine can be used to poll from interface.c 
00148          */
00149 
00150         if(!mudstate.alarm_triggered)
00151                 return;
00152         mudstate.alarm_triggered = 0;
00153         mudstate.now = time(NULL);
00154 
00155         do_second();
00156 
00157         /*
00158          * Free list reconstruction 
00159          */
00160 
00161         if((mudconf.control_flags & CF_DBCHECK) &&
00162            (mudstate.check_counter <= mudstate.now)) {
00163                 mudstate.check_counter = mudconf.check_interval + mudstate.now;
00164                 DPSET("< dbck >");
00165                 do_dbck(NOTHING, NOTHING, 0);
00166                 pcache_trim();
00167         }
00168         /*
00169          * Database dump routines 
00170          */
00171 
00172         if((mudconf.control_flags & CF_CHECKPOINT) &&
00173            (mudstate.dump_counter <= mudstate.now)) {
00174                 mudstate.dump_counter = mudconf.dump_interval + mudstate.now;
00175                 DPSET("< dump >");
00176                 fork_and_dump(0);
00177         }
00178         /*
00179            Mech stuff ; hopefully it means once ~per sec, although you
00180            can never be sure - therefore, the code does 'timejumps' as
00181            needed (see UpdateSpecialObjects for details)
00182          */
00183 
00184         if(mudconf.have_specials)
00185                 UpdateSpecialObjects();
00186 
00187         /*
00188          * Idle user check 
00189          */
00190 
00191         if((mudconf.control_flags & CF_IDLECHECK) &&
00192            (mudstate.idle_counter <= mudstate.now)) {
00193                 mudstate.idle_counter = mudconf.idle_interval + mudstate.now;
00194                 DPSET("< idlecheck >");
00195                 check_idle();
00196 
00197         }
00198         /*
00199          * Check for execution of attribute events 
00200          */
00201 
00202         if((mudconf.control_flags & CF_EVENTCHECK) &&
00203            (mudstate.events_counter <= mudstate.now)) {
00204                 mudstate.events_counter = 900 + mudstate.now;
00205                 DPSET("< eventcheck >");
00206                 check_events();
00207         }
00208 #ifdef HAVE_GETRUSAGE
00209         /*
00210          * Memory use stats 
00211          */
00212 
00213         if(mudstate.mstats_counter <= mudstate.now) {
00214 
00215                 int curr;
00216 
00217                 mudstate.mstats_counter = 15 + mudstate.now;
00218                 curr = mudstate.mstat_curr;
00219                 if(mudstate.now > mudstate.mstat_secs[curr]) {
00220 
00221                         struct rusage usage;
00222 
00223                         curr = 1 - curr;
00224                         getrusage(RUSAGE_SELF, &usage);
00225                         mudstate.mstat_ixrss[curr] = usage.ru_ixrss;
00226                         mudstate.mstat_idrss[curr] = usage.ru_idrss;
00227                         mudstate.mstat_isrss[curr] = usage.ru_isrss;
00228                         mudstate.mstat_secs[curr] = mudstate.now;
00229                         mudstate.mstat_curr = curr;
00230                 }
00231         }
00232 #endif
00233 
00234         mudstate.debug_cmd = cmdsave;
00235 }
00236 
00237 void timer_callback(int fd, short event, void *arg)
00238 {
00239         mudstate.alarm_triggered = 1;
00240         evtimer_add(&timer_event, &tv);
00241         dispatch();
00242 }
00243 
00247 void do_timewarp(dbref player, dbref cause, int key, char *arg)
00248 {
00249         int secs;
00250 
00251         secs = atoi(arg);
00252 
00253         if((key == 0) || (key & TWARP_QUEUE))   /*
00254                                                                                          * Sem/Wait queues 
00255                                                                                          */
00256                 do_queue(player, cause, QUEUE_WARP, arg);
00257         if(key & TWARP_DUMP)
00258                 mudstate.dump_counter -= secs;
00259         if(key & TWARP_CLEAN)
00260                 mudstate.check_counter -= secs;
00261         if(key & TWARP_IDLE)
00262                 mudstate.idle_counter -= secs;
00263         if(key & TWARP_EVENTS)
00264                 mudstate.events_counter -= secs;
00265 }

Generated on Mon May 28 04:25:25 2007 for BattletechMUX by  doxygen 1.4.7