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