/*************************************************************************** updates.cpp - updates scheduler / periodic tasks ------------------- begin : vr mei 16 2003 copyright : (C) 2003 by Meilof email : meilof@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #define POS_DEFAULTLOG #define POS_DEFAULTLOG_FILE #define POS_DEFAULTLOG_STDERR #define POS_DEFAULTLOG_SYSLOG #define POS_DEFAULTLOG_FPTR #include #include "updates.h" #include "secondary.h" #include "configuration.h" #include "zonefile.h" #include "resolver.h" #include #include time_t next_logfile; #ifdef _WIN32 HANDLE logfile_fd = INVALID_HANDLE_VALUE; #endif void open_new_logfile() { char logfile_name[PATH_MAX+8]; struct tm tstruct; time_t tsecs; FILE *flogfile = NULL; if (logfile_per_day) { char data[9]; char ext[5] = ""; strcpy(logfile_name, logfile); if (strlen(logfile_name) > 4 && logfile_name[strlen(logfile_name)-4] == '.') { strcpy(ext, logfile_name + strlen(logfile_name) - 4); logfile_name[strlen(logfile_name)-4] = 0; } tsecs = time(NULL); localtime_r(&tsecs, &tstruct); sprintf(data, "%04d%02d%02d", tstruct.tm_year + 1900, tstruct.tm_mon + 1, tstruct.tm_mday); strcat(logfile_name, data); strcat(logfile_name, ext); } else strcpy(logfile_name, logfile); #ifdef _WIN32 if (logfile_fd != INVALID_HANDLE_VALUE) CloseHandle(logfile_fd); logfile_fd = CreateFile(logfile_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL); if (logfile_fd == INVALID_HANDLE_VALUE) outfile = NULL; else (flogfile = fdopen(_open_osfhandle((long)logfile_fd, _O_APPEND | _O_TEXT), "a")); #else flogfile = try_fopen(logfile_name, "a"); #endif if (!flogfile) { pos_log(context_conf, log_warning, "Could not open log file %s for writing!\n", logfile_name); } outfile = flogfile; /* set next time */ if (logfile_per_day) { tstruct.tm_mday++; tstruct.tm_hour = 0; tstruct.tm_min = 0; tstruct.tm_sec = 0; next_logfile = mktime(&tstruct); } } class PendingUpdate { public: postime_t when; void *data; domainname dom; update_function fn; }; stl_list(PendingUpdate) update_list; void update_list_unregister(Zone *z) { stl_list(PendingUpdate)::iterator it = update_list.begin(); while (it != update_list.end()) { if (it->data == z) { it = update_list.erase(it); } else { it++; } } } void enqueue_update(postime_t when, domainname &dom, Zone *z, update_function fn) { PendingUpdate lst = { when, z, dom, fn }; stl_list(PendingUpdate)::iterator it = update_list.begin(); while (it != update_list.end() && it->when < when) it++; update_list.insert(it, lst); } void my_cleanup() { /* check whether to reset log */ printf("mc\n"); if (logfile_per_day) { time_t tsecs = time(NULL); if (tsecs >= next_logfile) open_new_logfile(); } /* cache cleanup/statistics */ pthread_mutex_lock(&m_cache); printf("mc2\n"); cache_cleanup(); if (cache_statistics) { pos_log(context_server, log_info, "Cache statistics: cd=%d dcd=%d ch=%d dch=%d cm=%d dcm=%d", n_cache_doms, delta_n_cache_doms, n_cache_hits, delta_n_cache_hits, n_cache_misses, delta_n_cache_misses); delta_n_cache_doms = 0; delta_n_cache_hits = 0; delta_n_cache_misses = 0; } pthread_mutex_unlock(&m_cache); /* checking enqueued updates... */ pthread_mutex_lock(&m_auth_zones); postime_t now = getcurtime(); domainname znroot; PendingUpdate obj; while (update_list.begin() != update_list.end() && update_list.begin()->when < now) { /* look up zone */ try { obj = *update_list.begin(); update_list.pop_front(); obj.fn(obj.dom, obj.data); } catch (PException p) { } } pthread_mutex_unlock(&m_auth_zones); } /* zone update functionality */ void start_zone_update(domainname dom, Zone *zn) { if (!zone_is_valid(dom, zn)) { pthread_mutex_lock(&m_auth_zones); return; } struct stat statstr; stl_string zonefile = zn->zonefile; if (stat(zonefile.c_str(), &statstr) != 0 || !S_ISREG(statstr.st_mode)) { /* file removed */ pos_log(context_zonedata, log_error, "Zone %s removed (zone file deleted)", dom.tocstr()); remove_base_zone(dom, (BaseZone **)&auth_root_zone); return; } if (zn->last_ftime == statstr.st_mtime) { /* no changes */ enqueue_update(getcurtime() + update_ttl*1000, dom, zn, (update_function)start_zone_update); return; } if (zn->type == Z_PRIMARY) { zn->feed_setting("reset", ""); zn->zonefile = zonefile; zn->end_setting(); } else { try { remove_base_zone(dom, (BaseZone **)&auth_root_zone); load_zone_file(dom, zonefile.c_str(), true); pos_log(context_server, log_info, "zone file %s (re)loaded", zonefile.c_str()); } catch (PException p) { pos_log(context_server, log_error, "error reloading zone file %s: %s", zonefile.c_str(), p.message); } } // enqueue_update(getcurtime() + zn->update_ttl*1000, dom, zn, (update_function)start_primaryzone_update); }