1 /* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> 2 3 This program is free software: you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation, either version 3 of the License, or 6 (at your option) any later version. 7 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License 14 along with this program. If not, see <https://www.gnu.org/licenses/>. 15 */ 16 17 #pragma once 18 19 #include <pthread.h> 20 #include <stdbool.h> 21 #include <sys/time.h> 22 23 #include "knot/conf/conf.h" 24 #include "knot/common/evsched.h" 25 #include "knot/worker/pool.h" 26 #include "libknot/db/db.h" 27 28 struct zone; 29 30 typedef enum zone_event_type { 31 ZONE_EVENT_INVALID = -1, 32 // supported event types 33 ZONE_EVENT_LOAD = 0, 34 ZONE_EVENT_REFRESH, 35 ZONE_EVENT_UPDATE, 36 ZONE_EVENT_EXPIRE, 37 ZONE_EVENT_FLUSH, 38 ZONE_EVENT_BACKUP, 39 ZONE_EVENT_NOTIFY, 40 ZONE_EVENT_DNSSEC, 41 ZONE_EVENT_UFREEZE, 42 ZONE_EVENT_UTHAW, 43 ZONE_EVENT_NSEC3RESALT, 44 ZONE_EVENT_DS_CHECK, 45 ZONE_EVENT_DS_PUSH, 46 // terminator 47 ZONE_EVENT_COUNT, 48 } zone_event_type_t; 49 50 typedef struct zone_events { 51 pthread_mutex_t mx; //!< Mutex protecting the struct. 52 pthread_mutex_t reschedule_lock;//!< Prevent concurrent reschedule() making mess. 53 54 zone_event_type_t type; //!< Type of running event. 55 bool running; //!< Some zone event is being run. 56 pthread_cond_t *run_end; //!< Notify this one after finishing a job. 57 58 bool frozen; //!< Terminated, don't schedule new events. 59 bool ufrozen; //!< Updates to the zone temporarily frozen by user. 60 61 event_t *event; //!< Scheduler event. 62 worker_pool_t *pool; //!< Server worker pool. 63 64 worker_task_t task; //!< Event execution context. 65 time_t time[ZONE_EVENT_COUNT]; //!< Event execution times. 66 bool forced[ZONE_EVENT_COUNT]; //!< Flag that the event was invoked by user ctl. 67 pthread_cond_t *blocking[ZONE_EVENT_COUNT]; //!< For blocking events: dispatching cond. 68 int result[ZONE_EVENT_COUNT]; //!< Event return values (in blocking operations). 69 } zone_events_t; 70 71 /*! 72 * \brief Initialize zone events. 73 * 74 * The function will not set up the scheduling, use \ref zone_events_setup 75 * to do that. 76 * 77 * \param zone Pointer to zone (context of execution). 78 * 79 * \return KNOT_E* 80 */ 81 int zone_events_init(struct zone *zone); 82 83 /*! 84 * \brief Set up zone events execution. 85 * 86 * \param zone Zone to setup. 87 * \param workers Worker thread pool. 88 * \param scheduler Event scheduler. 89 * 90 * \return KNOT_E* 91 */ 92 int zone_events_setup(struct zone *zone, worker_pool_t *workers, 93 evsched_t *scheduler); 94 95 /*! 96 * \brief Deinitialize zone events. 97 * 98 * \param zone Zone whose events we want to deinitialize. 99 */ 100 void zone_events_deinit(struct zone *zone); 101 102 /*! 103 * \brief Enqueue event type for asynchronous execution. 104 * 105 * \note This is similar to the scheduling an event for NOW, but it can 106 * bypass the event scheduler if no event is running at the moment. 107 * 108 * \param zone Zone to schedule new event for. 109 * \param type Type of event. 110 */ 111 void zone_events_enqueue(struct zone *zone, zone_event_type_t type); 112 113 /*! 114 * \brief Schedule new zone event. 115 * 116 * The function allows to set multiple events at once. 117 * 118 * The function intreprets time values (t) as follows: 119 * 120 * t > 0: schedule timer for a given time 121 * t = 0: cancel the timer 122 * t < 0: ignore change in the timer 123 * 124 * If the event is already scheduled, the new time will be set only if the 125 * new time is earlier than the currently scheduled one. To override the 126 * check, cancel and schedule the event in a single function call. 127 * 128 * \param zone Zone to schedule new event for. 129 * \param ... Sequence of zone_event_type_t and time_t terminated with 130 * ZONE_EVENT_INVALID. 131 */ 132 void _zone_events_schedule_at(struct zone *zone, ...); 133 134 #define zone_events_schedule_at(zone, events...) \ 135 _zone_events_schedule_at(zone, events, ZONE_EVENT_INVALID) 136 137 #define zone_events_schedule_now(zone, type) \ 138 zone_events_schedule_at(zone, type, time(NULL)) 139 140 /*! 141 * \brief Schedule zone event to now, with forced flag. 142 */ 143 void zone_events_schedule_user(struct zone *zone, zone_event_type_t type); 144 145 /*! 146 * \brief Schedule new zone event as soon as possible and wait for it's 147 * completion (end of task run), with optional forced flag. 148 * 149 * \param zone Zone to schedule new event for. 150 * \param type Zone event type. 151 * \param user Forced flag indication. 152 * 153 * \return KNOT_E* 154 */ 155 int zone_events_schedule_blocking(struct zone *zone, zone_event_type_t type, bool user); 156 157 /*! 158 * \brief Freeze all zone events and prevent new events from running. 159 * 160 * \param zone Zone to freeze events for. 161 */ 162 void zone_events_freeze(struct zone *zone); 163 164 /*! 165 * \brief Freeze zone events and wait for running event to finish. 166 * 167 * \param zone Zone to freeze events for. 168 */ 169 void zone_events_freeze_blocking(struct zone *zone); 170 171 /*! 172 * \brief ufreeze_applies 173 * \param type Type of event to be checked 174 * \return true / false if user freeze applies 175 */ 176 bool ufreeze_applies(zone_event_type_t type); 177 178 /*! 179 * \brief Start the events processing. 180 * 181 * \param zone Zone to start processing for. 182 */ 183 void zone_events_start(struct zone *zone); 184 185 /*! 186 * \brief Return time of the occurrence of the given event. 187 * 188 * \param zone Zone to get event time from. 189 * \param type Event type. 190 * 191 * \retval time of the event when event found 192 * \retval 0 when the event is not planned 193 * \retval negative value if event is invalid 194 */ 195 time_t zone_events_get_time(const struct zone *zone, zone_event_type_t type); 196 197 /*! 198 * \brief Return text name of the event. 199 * 200 * \param type Type of event. 201 * 202 * \retval String with event name if it exists. 203 * \retval NULL if the event does not exist. 204 */ 205 const char *zone_events_get_name(zone_event_type_t type); 206 207 /*! 208 * \brief Return time and type of the next event. 209 * 210 * \param zone Zone to get next event from. 211 * \param type [out] Type of the next event will be stored in the parameter. 212 * 213 * \return time of the next event or an error (negative number) 214 */ 215 time_t zone_events_get_next(const struct zone *zone, zone_event_type_t *type); 216