summaryrefslogtreecommitdiff
path: root/source3/lib/events.c
blob: d6f3c328288d5e51e5bfe1e1c24f77d9da763bfb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
   Unix SMB/CIFS implementation.
   Timed event library.
   Copyright (C) Andrew Tridgell 1992-1998
   Copyright (C) Volker Lendecke 2005

   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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "includes.h"

static struct timed_event *timed_events;

static int timed_event_destructor(struct timed_event *te)
{
	DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te,
		te->event_name));
	DLIST_REMOVE(timed_events, te);
	return 0;
}

/****************************************************************************
 Schedule a function for future calling, cancel with TALLOC_FREE().
 It's the responsibility of the handler to call TALLOC_FREE() on the event
 handed to it.
****************************************************************************/

struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx,
				struct timeval when,
				const char *event_name,
				void (*handler)(struct timed_event *te,
						const struct timeval *now,
						void *private_data),
				void *private_data)
{
	struct timed_event *te, *last_te, *cur_te;

	te = TALLOC_P(mem_ctx, struct timed_event);
	if (te == NULL) {
		DEBUG(0, ("talloc failed\n"));
		return NULL;
	}

	te->when = when;
	te->event_name = event_name;
	te->handler = handler;
	te->private_data = private_data;

	/* keep the list ordered - this is NOT guarenteed as event times
	   may be changed after insertion */
	last_te = NULL;
	for (cur_te = timed_events; cur_te; cur_te = cur_te->next) {
		/* if the new event comes before the current one break */
		if (!timeval_is_zero(&cur_te->when) &&
				timeval_compare(&te->when, &cur_te->when) < 0) {
			break;
		}
		last_te = cur_te;
	}

	DLIST_ADD_AFTER(timed_events, te, last_te);
	talloc_set_destructor(te, timed_event_destructor);

	DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name,
			(unsigned long)te));
	return te;
}

void run_events(void)
{
	/* Run all events that are pending, not just one (as we
	   did previously. */

	while (timed_events) {
		struct timeval now;
		GetTimeOfDay(&now);

		if (timeval_compare(&now, &timed_events->when) < 0) {
			/* Nothing to do yet */
			DEBUG(11, ("run_events: Nothing to do\n"));
			return;
		}

		DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name,
			(unsigned long)timed_events));

		timed_events->handler(timed_events, &now, timed_events->private_data);
	}
}

struct timeval *get_timed_events_timeout(struct timeval *to_ret)
{
	struct timeval now;

	if (timed_events == NULL) {
		return NULL;
	}

	now = timeval_current();
	*to_ret = timeval_until(&now, &timed_events->when);

	DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)to_ret->tv_sec,
		(int)to_ret->tv_usec));

	return to_ret;
}

int set_event_dispatch_time(const char *event_name, struct timeval when)
{
	int num_events = 0;
	struct timed_event *te;

	for (te = timed_events; te; te = te->next) {
		if (strcmp(event_name, te->event_name) == 0) {
			te->when = when;
			num_events++;
		}
	}
	return num_events;
}