1 /*
2    Unix SMB/CIFS implementation.
3    Timed event library.
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Volker Lendecke 2005-2007
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "includes.h"
22 #include "util_event.h"
23 
24 struct idle_event {
25 	struct tevent_timer *te;
26 	struct timeval interval;
27 	char *name;
28 	bool (*handler)(const struct timeval *now, void *private_data);
29 	void *private_data;
30 };
31 
smbd_idle_event_handler(struct tevent_context * ctx,struct tevent_timer * te,struct timeval now,void * private_data)32 static void smbd_idle_event_handler(struct tevent_context *ctx,
33 				    struct tevent_timer *te,
34 				    struct timeval now,
35 				    void *private_data)
36 {
37 	struct idle_event *event =
38 		talloc_get_type_abort(private_data, struct idle_event);
39 
40 	TALLOC_FREE(event->te);
41 
42 	DEBUG(10,("smbd_idle_event_handler: %s %p called\n",
43 		  event->name, event->te));
44 
45 	if (!event->handler(&now, event->private_data)) {
46 		DEBUG(10,("smbd_idle_event_handler: %s %p stopped\n",
47 			  event->name, event->te));
48 		/* Don't repeat, delete ourselves */
49 		TALLOC_FREE(event);
50 		return;
51 	}
52 
53 	DEBUG(10,("smbd_idle_event_handler: %s %p rescheduled\n",
54 		  event->name, event->te));
55 
56 	event->te = tevent_add_timer(ctx, event,
57 				     timeval_sum(&now, &event->interval),
58 				     smbd_idle_event_handler, event);
59 
60 	/* We can't do much but fail here. */
61 	SMB_ASSERT(event->te != NULL);
62 }
63 
event_add_idle(struct tevent_context * event_ctx,TALLOC_CTX * mem_ctx,struct timeval interval,const char * name,bool (* handler)(const struct timeval * now,void * private_data),void * private_data)64 struct idle_event *event_add_idle(struct tevent_context *event_ctx,
65 				  TALLOC_CTX *mem_ctx,
66 				  struct timeval interval,
67 				  const char *name,
68 				  bool (*handler)(const struct timeval *now,
69 						  void *private_data),
70 				  void *private_data)
71 {
72 	struct idle_event *result;
73 	struct timeval now = timeval_current();
74 
75 	result = talloc(mem_ctx, struct idle_event);
76 	if (result == NULL) {
77 		DEBUG(0, ("talloc failed\n"));
78 		return NULL;
79 	}
80 
81 	result->interval = interval;
82 	result->handler = handler;
83 	result->private_data = private_data;
84 
85 	if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
86 		DEBUG(0, ("talloc failed\n"));
87 		TALLOC_FREE(result);
88 		return NULL;
89 	}
90 
91 	result->te = tevent_add_timer(event_ctx, result,
92 				      timeval_sum(&now, &interval),
93 				      smbd_idle_event_handler, result);
94 	if (result->te == NULL) {
95 		DEBUG(0, ("event_add_timed failed\n"));
96 		TALLOC_FREE(result);
97 		return NULL;
98 	}
99 
100 	DEBUG(10,("event_add_idle: %s %p\n", result->name, result->te));
101 	return result;
102 }
103