Logo Search packages:      
Sourcecode: bayonne version File versions  Download package

scheduler.cpp

// Copyright (C) 2000-2001 Open Source Telecom Corporation.
//  
// 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.

#include "server.h"
#include <ctype.h>

#ifdef CCXX_NAMESPACES
namespace ost {
using namespace std;
#endif

Scheduler::Scheduler() : ThreadLock()
{
      char path[65];
      const char *cp;

      interval = 0;
      altschedule = NULL;

      resHour = resMinute = -1;

      if(canModify(keypaths.getRunfiles()))
            sprintf(path, "%s/bayonne.sched", keypaths.getRunfiles());
      else
            sprintf(path, "%s/.bayonne.sched", getenv("HOME"));

      remove(path);
      rtmp = creat(path, 0640);
      
      chown(path, keyserver.getUid(), keyserver.getGid());
      sched.close();

      cp = keyserver.getLast("restart");
      if(!cp)
            return;

      resHour = atoi(cp);
      resMinute = 0;
      cp = strchr(cp, ':');
      if(!cp)
            return;

      resMinute = atoi(++cp);
}

Scheduler::~Scheduler(void)
{
      ::close(rtmp);
      sched.close();
}

void Scheduler::altSchedule(const char *sch)
{
      if(sch)
            slog(Slog::levelInfo) << "scheduler: " << sch << ": alternate schedule activated" << endl;
      else
            slog(Slog::levelInfo) << "scheduler: alternate schedule cleared" << endl;
      altschedule = sch;
      interval = 0;
}

void Scheduler::initial(void)
{
      const char *etc;
      char cfgpath[128];
      if(sched.is_open())
            sched.close();

      strcpy(cfgpath, keyserver.getPrefix());
      strcat(cfgpath, "/scheduler.conf");
      if(!canAccess(cfgpath))
      {
            etc = keypaths.getLast("etc");
            etc = strchr(etc + 1, '/');
            if(etc)
                  ++etc;
            else
                  etc = "";
      
            strcpy(cfgpath, keypaths.getLast("etc"));
            if(*etc)
                  strcat(cfgpath, "scheduler.conf");
            else
                  strcat(cfgpath, "bayonne.sched");
      }

      sched.open(cfgpath);
      if(!sched.is_open())
            slog(Slog::levelWarning) << "scheduler: " << cfgpath << ": cannot access" << endl;
      else
      {
            slog(Slog::levelNotice) << "scheduler: using " << cfgpath << endl;
            interval = load();
            update();
      }
}

void Scheduler::stop(void)
{
      slog(Slog::levelDebug) << "scheduler: stopped" << endl;
      sched.close();
      ::close(rtmp);
}

void Scheduler::sync(void)
{
      Sync *sync;
      time_t now;
      struct tm *dt;

      slog(Slog::levelDebug) << "scheduler starting..." << endl;
      Session::clean();
      time(&now);
      dt = localtime(&now);

      if(dt->tm_hour == resHour && dt->tm_min == resMinute && driver->isIdle())
      {
            restart_server = true;
            kill(mainpid, SIGINT);
            return;
      }

      sync = Sync::first;
      while(sync)
      {
            if(((time_t)sync->runtime + 60 * (time_t)sync->getInterval()) < now)
            {
                  time(&sync->runtime);
                  if(sync->isScheduled())
                  {
                        slog(Slog::levelInfo) << "scheduler: " << sync->getSyncName() << " updated" << endl;
                        sync->schedule();
                  }
            }
            sync = sync->next;
      }
            
      if(!sched)
            initial();

      if(!sched.is_open() || interval > 0)
            --interval;
      else if(interval < 1)
      {
            interval = load();
            update();
      }
}

void Scheduler::update(void)
{
      schedtmp tmp;

      TrunkGroup *grp = TrunkGroup::first;
      if(rtmp < 0)
            return;

      lseek(rtmp, 0l, SEEK_SET);
      while(grp)
      {
            memset(&tmp, 0, sizeof(tmp));
            strncpy(tmp.grp, grp->getName(), sizeof(tmp.grp));
            grp->getSchedule(tmp.scr);
            write(rtmp, (char *)&tmp, sizeof(tmp));
            grp = grp->next;
      } 
}

int Scheduler::load(void)
{
      static char *days[7] = {
            "su", "mo", "tu", "we", "th", "fr", "sa"};

      static char *months[12] = {
            "jan", "feb", "mar", "apr", "may", "jun",
            "jul", "aug", "sep", "oct", "nov", "dec"};

      TrunkGroup *group;
      time_t now;
      struct tm *dt;
      char lbuf[256];
      char *name, *day, *start, *cp;
      char *p;
      int hr, min;
      int td;
      char *sp = lbuf;
      struct tm tbuf;
      unsigned dayflag;
      int len;
      int dom = 0;
      int mins;

      time(&now);
      dt = localtime_r(&now, &tbuf);

      if(!sched.is_open())
      {
            group = TrunkGroup::first;
            while(group)
            {
                  group->setSchedule(NULL);
                  group = group->next;
            }
            return keythreads.getInterval();
      }
      
      sched.seekg(0);
      sched.clear();


      group = TrunkGroup::first;
      while(group)
      {
            group->trump = 0;
            group->planned[0] = 0;
            group = group->next;
      }

      for(;;)
      {
            sched.getline(lbuf, 255);
            if(sched.eof())  
                  break;
      
            name = lbuf;
            while(*name && isspace(*name))
                  ++name;

            if(!*name || *name == '#' || *name == ';')
                  continue;

            name = strtok_r(name, " \t\n", &sp);
            day = strtok_r(NULL, " \t\n", &sp);
            start = strtok_r(NULL, " \t\n", &sp);
            cp = strtok_r(NULL, " \t\n", &sp);
            if(!cp || !day || !start)
            {
                  slog(Slog::levelError) << "error in schedule" << endl;
                  continue;
            }

            dayflag = 0;
            if(!stricmp(day, "*"))
                  dayflag = 10000;
 
            day = strtok_r(day, ".,;", &sp);
            while(day && !dayflag)
            {
                  if(altschedule)
                  {
                        if(!stricmp(day, altschedule))
                        {
                              dayflag = 50000;
                              break;
                        }
                  }

                  // check for holidays whose date changes each year
                  //  -- greg@zipcar.com

                  if(!stricmp(day, "us_columbus_day"))
                  {
                        // Columbus day
                        // observed on the second Monday in October.
                        
                        if(dt->tm_mon == 9 && dt->tm_wday == 1 && dt->tm_mday >= 8 && dt->tm_mday <= 14)
                              dayflag = 40000;
                  }
                  else if(!stricmp(day, "us_election_day"))
                  {
                        // Election Day
                        // observed on the first Tuesday in November
                        
                        if(dt->tm_mon == 10 && dt->tm_wday == 2 && dt->tm_mday >= 1 && dt->tm_mday <= 7)
                              dayflag = 40000;
                  }
                  else if(!stricmp(day, "us_labor_day"))
                  {
                        // Labor day
                        // observed on the first Monday in September
                        
                        if(dt->tm_mon == 8 && dt->tm_wday == 1 && dt->tm_mday >= 1 && dt->tm_mday <= 7)
                              dayflag = 40000;
                  }
                  else if(!stricmp(day, "us_martin_luther_king_birthday"))
                  {
                        // Martin Luther King day
                        // observed on the third Monday in January.

                        if(dt->tm_mon == 0 && dt->tm_wday == 1 && dt->tm_mday >= 15 && dt->tm_mday <= 21)
                              dayflag = 40000;
                  }
                  else if(!stricmp(day, "us_memorial_day"))
                  {
                        // Memorial day
                        // observed on the last Monday in May
                        
                        if(dt->tm_mon == 3 && dt->tm_wday == 1 && dt->tm_mday >= 25 && dt->tm_mday <= 31)
                              dayflag = 40000;
                  }
                  else if(!stricmp(day, "us_presidents_day") || !stricmp(day, "us_washington_birthday"))
                  {
                        // President's day aka Washington's birthday
                        // observed on the third Monday in February
                        
                        if(dt->tm_mon == 1 && dt->tm_wday == 1 && dt->tm_mday >= 15 && dt->tm_mday <= 21)
                              dayflag = 40000;
                  }
                  else if(!stricmp(day, "us_thanksgiving"))
                  {
                        // Thanksgiving
                        // observed on the fourth Thursday in November
                        
                        if(dt->tm_mon == 10 && dt->tm_wday == 4 && dt->tm_mday >= 22 && dt->tm_mday <= 28)
                              dayflag = 40000;
                  }
                        
                  len = strlen(day);
                  if(len > 3)
                  {
                        if(day[len - 2] >= '0' && day[len - 2] <= '9')
                              dom = atoi(&day[len - 2]);
                        else
                              dom = atoi(&day[len - 1]);

                        if(dom == dt->tm_mday && !strnicmp(day, months[dt->tm_mon], 3))
                        {
                              dayflag = 30000;
                              break;
                        }           
                  }

                  if(!strnicmp(day, days[dt->tm_wday], 2))
                        dayflag = 20000;

                  if(!dayflag)
                        day = strtok_r(NULL, ".,;", &sp);
            }

            if(!dayflag)
                  continue;         

            if (!strcmp(start,"*" )) 
                  hr = min = 0;
            else 
            {
                  hr = atoi(start);
                  min = atoi(strchr(start, ':') + 1); 
            }                 

            if(hr > dt->tm_hour || (hr == dt->tm_hour && min > dt->tm_min))
                  continue;

            dayflag += 100 * hr + min;
            if(!strcmp(name, "*"))
            {
                  if ( !( group = TrunkGroup::first ) ) 
                        slog( Slog::levelWarning ) << "scheduler: could not find any groups" << endl;
                  while(group)
                  {
                        if(dayflag > group->trump)
                        {
                              group->trump = dayflag;
                              strcpy(group->planned, cp);
                        }
                        group = group->next;
                  }
                  continue;
            }

            p = strtok_r(name, ",;", &sp);      
            while(p)
            {
                  group = getGroup(p);
                  if(!group) 
                  { 
                        slog( Slog::levelWarning ) << "scheduler::unknown group '" << p << "' refereced in schedule" << endl;
                        p = strtok_r(NULL, ",;", &sp);
                        continue;
                  } 
                  else if(dayflag > group->trump)
                  {
                        group->trump = dayflag;
                        strcpy(group->planned, cp);
                  }
                  p = strtok_r(NULL, ",;", &sp);
            }
      }

      group = TrunkGroup::first;
      while(group)
      {
            group->setSchedule(group->planned);
            group = group->next;
      }

      sched.clear(); // Probably we've hit an EOF - so we must clear fail()

      mins = keythreads.getInterval();
      td = ((dt->tm_hour * 60) + dt->tm_min) % mins;
      return mins - td;
}
                              
#ifdef      CCXX_NAMESPACES
};
#endif

Generated by  Doxygen 1.6.0   Back to index