xref: /titanic_54/usr/src/cmd/cron/elm.c (revision e2553d6841698282283135811d10eebeefb512bc)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*e2553d68SSerge Dussud  * Common Development and Distribution License (the "License").
6*e2553d68SSerge Dussud  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate 
22032624d5Sbasabi /*
23*e2553d68SSerge Dussud  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24032624d5Sbasabi  * Use is subject to license terms.
25032624d5Sbasabi  */
26032624d5Sbasabi 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate 
32*e2553d68SSerge Dussud /* ********************************************************************** */
33*e2553d68SSerge Dussud /* *		General-Purpose Event List Manager			* */
34*e2553d68SSerge Dussud /* ********************************************************************** */
35*e2553d68SSerge Dussud /*
36*e2553d68SSerge Dussud  *	description:	These routines maintain a time-ordered list of events.
37*e2553d68SSerge Dussud  *	functions available:
38*e2553d68SSerge Dussud  *		init :	Creates and initializes the data structure.
39*e2553d68SSerge Dussud  *			See the reference for parameters to init.
40*e2553d68SSerge Dussud  *		add(&event, time, id) :	Adds an event to the list.
41*e2553d68SSerge Dussud  *					Returns: 0 if success,
42*e2553d68SSerge Dussud  *						-2 if event time is lower
43*e2553d68SSerge Dussud  *						   than Lower Bound time LB
44*e2553d68SSerge Dussud  *						-1 else
45*e2553d68SSerge Dussud  *		remove(id) :	Removes events (with appropriate id).
46*e2553d68SSerge Dussud  *		empty : Returns true if the list is empty, false otherwise.
47*e2553d68SSerge Dussud  *		first :	Removes the element at the head of the list.
48*e2553d68SSerge Dussud  *			Returns a pointer to the event.
49*e2553d68SSerge Dussud  *		delete : Frees up all allocated storage associated
50*e2553d68SSerge Dussud  *			 with the event list.
51*e2553d68SSerge Dussud  *	reference:	Franta, W. R. and Maly, K.,
52*e2553d68SSerge Dussud  *			"An efficient data structure for the
53*e2553d68SSerge Dussud  *			simulation event set ", CACM Vol. 20(8),
54*e2553d68SSerge Dussud  *			Aug 1977, pp. 596-602.
55*e2553d68SSerge Dussud  *	machine dependant:	the constant INFINITY
56*e2553d68SSerge Dussud  */
57*e2553d68SSerge Dussud /* ********************************************************************** */
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate #include <sys/types.h>
617c478bd9Sstevel@tonic-gate #include <stdlib.h>
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate extern	void *xmalloc(size_t);
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #define	INFINITY	2147483647L	/* upper bound on time	*/
667c478bd9Sstevel@tonic-gate #define	NULL		0		/* a null pointer 	*/
677c478bd9Sstevel@tonic-gate #define	TRUE		1
687c478bd9Sstevel@tonic-gate #define	FALSE		0
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate /* the following parameters are set in init	*/
717c478bd9Sstevel@tonic-gate static int	DU;		/* number of time intervals	*/
727c478bd9Sstevel@tonic-gate static time_t	LB;		/* lower bound on time	*/
737c478bd9Sstevel@tonic-gate static time_t	DT;		/* width of interval	*/
747c478bd9Sstevel@tonic-gate static int	NLIM;		/* max notices per sublist	*/
757c478bd9Sstevel@tonic-gate 
76*e2553d68SSerge Dussud /*
77*e2553d68SSerge Dussud  * a notice points to an event.  a notice has the following fields:
78*e2553d68SSerge Dussud  *	time = time of the event.
79*e2553d68SSerge Dussud  *	id = identifier for an event or class of events that may need
80*e2553d68SSerge Dussud  *		to be removed (other than at the front of the list).
81*e2553d68SSerge Dussud  *	event = pointer to the event.
82*e2553d68SSerge Dussud  *	isdummy = tells whether this notice points to a real event or
83*e2553d68SSerge Dussud  *		is just a dummy notice (one that is used to "mark off"
84*e2553d68SSerge Dussud  *		the time intervals that the user specifies in init).
85*e2553d68SSerge Dussud  *	key = points back to the key that points to this notice,
86*e2553d68SSerge Dussud  *		if there is one.
87*e2553d68SSerge Dussud  *	left = points to the notice immediately preceding this one.
88*e2553d68SSerge Dussud  *	right = points to the notice immediately following this one.
89*e2553d68SSerge Dussud  */
907c478bd9Sstevel@tonic-gate struct notice {	time_t	time;
917c478bd9Sstevel@tonic-gate 		int	id;
927c478bd9Sstevel@tonic-gate 		void	*event;
937c478bd9Sstevel@tonic-gate 		short int	isdummy;
947c478bd9Sstevel@tonic-gate 		struct key	*key;
957c478bd9Sstevel@tonic-gate 		struct notice	*left;
967c478bd9Sstevel@tonic-gate 		struct notice	*right; };
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /* current points to the front of the list of notices (events)	*/
997c478bd9Sstevel@tonic-gate struct notice	*current = NULL;
1007c478bd9Sstevel@tonic-gate 
101*e2553d68SSerge Dussud /*
102*e2553d68SSerge Dussud  * a key points to a sublist of notices.  a key has the following fields:
103*e2553d68SSerge Dussud  *	time = max time of notices in sublist.
104*e2553d68SSerge Dussud  *	numnote = number of notices in sublist.
105*e2553d68SSerge Dussud  *	notice = pointer to the notice with max time.
106*e2553d68SSerge Dussud  *	left = points to the key immediately preceding this one.
107*e2553d68SSerge Dussud  *	right = points to the key immediately following this one.
108*e2553d68SSerge Dussud  */
1097c478bd9Sstevel@tonic-gate struct key {	time_t	time;
1107c478bd9Sstevel@tonic-gate 		int	numnote;
1117c478bd9Sstevel@tonic-gate 		struct notice	*notice;
1127c478bd9Sstevel@tonic-gate 		struct key	*left;
1137c478bd9Sstevel@tonic-gate 		struct key	*right; };
1147c478bd9Sstevel@tonic-gate 
115*e2553d68SSerge Dussud /*
116*e2553d68SSerge Dussud  * the index list breaks the keys into time intervals as specified in init.
117*e2553d68SSerge Dussud  * the index is "shifted" one time interval whenever el_first returns an
118*e2553d68SSerge Dussud  * event with a time greater than the max time of the first interval
119*e2553d68SSerge Dussud  * (eg. with intervals of a day which span one week (MTWTFSS),
120*e2553d68SSerge Dussud  * if el_first finds the next event is on tuesday, then
121*e2553d68SSerge Dussud  * the intervals of the event list get shifted (TWTFSSM).
122*e2553d68SSerge Dussud  */
1237c478bd9Sstevel@tonic-gate struct index {	struct key *key;
1247c478bd9Sstevel@tonic-gate 		struct index *right; };
1257c478bd9Sstevel@tonic-gate 
126*e2553d68SSerge Dussud /* index pts to the front of the index list */
127*e2553d68SSerge Dussud static struct index *index = NULL;
1287c478bd9Sstevel@tonic-gate 
129*e2553d68SSerge Dussud /* ******************* */
1307c478bd9Sstevel@tonic-gate void
1317c478bd9Sstevel@tonic-gate el_init(du, lb, dt, nlim)
132*e2553d68SSerge Dussud /* ******************* */
1337c478bd9Sstevel@tonic-gate int du, nlim;
1347c478bd9Sstevel@tonic-gate time_t lb, dt;
1357c478bd9Sstevel@tonic-gate {
1367c478bd9Sstevel@tonic-gate 	int	i;
1377c478bd9Sstevel@tonic-gate 	time_t	t;
1387c478bd9Sstevel@tonic-gate 	struct index *indprev, *ind;
1397c478bd9Sstevel@tonic-gate 	struct key *kprev, *k;
1407c478bd9Sstevel@tonic-gate 	struct notice *nprev, *n;
1417c478bd9Sstevel@tonic-gate 
142*e2553d68SSerge Dussud 	if ((du < 1) || (dt < 1) || (nlim < 1))
143*e2553d68SSerge Dussud 		return;
1447c478bd9Sstevel@tonic-gate 	DU = du + 1;
1457c478bd9Sstevel@tonic-gate 	LB = lb;
1467c478bd9Sstevel@tonic-gate 	DT = dt;
1477c478bd9Sstevel@tonic-gate 	NLIM = nlim;
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	/*
1507c478bd9Sstevel@tonic-gate 	 * initialize index, keys, and notices
1517c478bd9Sstevel@tonic-gate 	 */
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	/* create first dummy notice */
1547c478bd9Sstevel@tonic-gate 	n = (struct notice *)xmalloc(sizeof (struct notice));
1557c478bd9Sstevel@tonic-gate 	n->time = LB;
1567c478bd9Sstevel@tonic-gate 	n->isdummy = TRUE;
1577c478bd9Sstevel@tonic-gate 	n->left = NULL;
1587c478bd9Sstevel@tonic-gate 	nprev = n;
1597c478bd9Sstevel@tonic-gate 	/* create first dummy key */
1607c478bd9Sstevel@tonic-gate 	k = (struct key *)xmalloc(sizeof (struct key));
1617c478bd9Sstevel@tonic-gate 	k->time = LB;
1627c478bd9Sstevel@tonic-gate 	k->numnote = 1;
1637c478bd9Sstevel@tonic-gate 	k->notice = n;
1647c478bd9Sstevel@tonic-gate 	k->left = NULL;
1657c478bd9Sstevel@tonic-gate 	kprev = k;
1667c478bd9Sstevel@tonic-gate 	/* make notice point to key */
1677c478bd9Sstevel@tonic-gate 	n->key = k;
1687c478bd9Sstevel@tonic-gate 	/* no index element to allocate this time */
1697c478bd9Sstevel@tonic-gate 	indprev = NULL;
1707c478bd9Sstevel@tonic-gate 	/* create dummy notices, dummy keys, and index elements */
1717c478bd9Sstevel@tonic-gate 	t = LB;
1727c478bd9Sstevel@tonic-gate 	for (i = 1; i < DU; i++) {
1737c478bd9Sstevel@tonic-gate 		t = t + DT;
1747c478bd9Sstevel@tonic-gate 		n = (struct notice *)xmalloc(sizeof (struct notice));
1757c478bd9Sstevel@tonic-gate 		n->time = t;
1767c478bd9Sstevel@tonic-gate 		n->isdummy = TRUE;
1777c478bd9Sstevel@tonic-gate 		n->left = nprev;
1787c478bd9Sstevel@tonic-gate 		nprev->right = n;
1797c478bd9Sstevel@tonic-gate 		nprev = n;
1807c478bd9Sstevel@tonic-gate 		k = (struct key *)xmalloc(sizeof (struct key));
1817c478bd9Sstevel@tonic-gate 		k->time = t;
1827c478bd9Sstevel@tonic-gate 		k->numnote = 1;
1837c478bd9Sstevel@tonic-gate 		k->notice = n;
1847c478bd9Sstevel@tonic-gate 		k->left = kprev;
1857c478bd9Sstevel@tonic-gate 		kprev->right = k;
1867c478bd9Sstevel@tonic-gate 		kprev = k;
1877c478bd9Sstevel@tonic-gate 		n->key = k;
1887c478bd9Sstevel@tonic-gate 		ind = (struct index *)xmalloc(sizeof (struct index));
1897c478bd9Sstevel@tonic-gate 		ind->key = k;
190*e2553d68SSerge Dussud 		if (indprev == NULL)
191*e2553d68SSerge Dussud 			index = ind;
192*e2553d68SSerge Dussud 		else
193*e2553d68SSerge Dussud 			indprev->right = ind;
1947c478bd9Sstevel@tonic-gate 		indprev = ind; }
1957c478bd9Sstevel@tonic-gate 	/* create last dummy notice */
1967c478bd9Sstevel@tonic-gate 	n = (struct notice *)xmalloc(sizeof (struct notice));
1977c478bd9Sstevel@tonic-gate 	n->time = INFINITY;
1987c478bd9Sstevel@tonic-gate 	n->isdummy = TRUE;
1997c478bd9Sstevel@tonic-gate 	n->left = nprev;
2007c478bd9Sstevel@tonic-gate 	n->right = NULL;
2017c478bd9Sstevel@tonic-gate 	nprev->right = n;
2027c478bd9Sstevel@tonic-gate 	/* create last dummy key */
2037c478bd9Sstevel@tonic-gate 	k = (struct key *)xmalloc(sizeof (struct key));
2047c478bd9Sstevel@tonic-gate 	k->time = INFINITY;
2057c478bd9Sstevel@tonic-gate 	k->numnote = 1;
2067c478bd9Sstevel@tonic-gate 	k->notice = n;
2077c478bd9Sstevel@tonic-gate 	k->left = kprev;
2087c478bd9Sstevel@tonic-gate 	k->right = NULL;
2097c478bd9Sstevel@tonic-gate 	kprev->right = k;
2107c478bd9Sstevel@tonic-gate 	n->key = k;
2117c478bd9Sstevel@tonic-gate 	/* create last index element */
2127c478bd9Sstevel@tonic-gate 	ind = (struct index *)xmalloc(sizeof (struct index));
2137c478bd9Sstevel@tonic-gate 	ind->key = k;
2147c478bd9Sstevel@tonic-gate 	ind->right = NULL;
2157c478bd9Sstevel@tonic-gate 	indprev->right = ind;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	current = NULL;
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 
221*e2553d68SSerge Dussud /* ********************** */
222*e2553d68SSerge Dussud int
2237c478bd9Sstevel@tonic-gate el_add(event, time, id)
224*e2553d68SSerge Dussud /* ********************** */
2257c478bd9Sstevel@tonic-gate void	*event;
2267c478bd9Sstevel@tonic-gate int	id;
2277c478bd9Sstevel@tonic-gate time_t	time;
2287c478bd9Sstevel@tonic-gate {
229*e2553d68SSerge Dussud 	/*
230*e2553d68SSerge Dussud 	 * add works slightly differently than in the reference.  if the
231*e2553d68SSerge Dussud 	 * sublist to be inserted into is full (numnote = NLIM),
232*e2553d68SSerge Dussud 	 * the sublist is split in half.  thus the size of the sublists
233*e2553d68SSerge Dussud 	 * in this implementation normally ranges from NLIM/2 to NLIM.
234*e2553d68SSerge Dussud 	 */
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	struct index *ind;
2377c478bd9Sstevel@tonic-gate 	struct key *k, *k2;
2387c478bd9Sstevel@tonic-gate 	struct notice *n, *n2;
2397c478bd9Sstevel@tonic-gate 	int i;
2407c478bd9Sstevel@tonic-gate 
241*e2553d68SSerge Dussud 	/*
242*e2553d68SSerge Dussud 	 * time may be 0 when set by next_time() on error or an
243*e2553d68SSerge Dussud 	 * invalid time specification of job
244*e2553d68SSerge Dussud 	 */
245*e2553d68SSerge Dussud 	if ((index == NULL) || (time <= 0)) {
246*e2553d68SSerge Dussud 		return (-1);
247*e2553d68SSerge Dussud 	}
248*e2553d68SSerge Dussud 	if (time < LB) {
249*e2553d68SSerge Dussud 		return (-2);
250*e2553d68SSerge Dussud 	}
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	/* allocate new notice */
2537c478bd9Sstevel@tonic-gate 	n = (struct notice *)xmalloc(sizeof (struct notice));
2547c478bd9Sstevel@tonic-gate 	n->time = time;
2557c478bd9Sstevel@tonic-gate 	n->id = id;
2567c478bd9Sstevel@tonic-gate 	n->event = event;
2577c478bd9Sstevel@tonic-gate 	n->isdummy = FALSE;
2587c478bd9Sstevel@tonic-gate 	n->key = NULL;
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	/* find the right interval */
2617c478bd9Sstevel@tonic-gate 	ind = index;
2627c478bd9Sstevel@tonic-gate 	while ((ind->key)->time <= time) ind = ind->right;
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	/* find the right key */
2657c478bd9Sstevel@tonic-gate 	k = (ind->key)->left;
2667c478bd9Sstevel@tonic-gate 	while (k->time > time) k = k->left;
2677c478bd9Sstevel@tonic-gate 	k = k->right;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	/* (k->time>time) and ((k->left)->time<=time) */
2707c478bd9Sstevel@tonic-gate 	if (k->numnote == NLIM) {
2717c478bd9Sstevel@tonic-gate 		/* k's sublist is full, so split it */
2727c478bd9Sstevel@tonic-gate 		k->numnote = NLIM / 2;
2737c478bd9Sstevel@tonic-gate 		n2 = k->notice;
2747c478bd9Sstevel@tonic-gate 		for (i = 1; i <= NLIM/2; i++) n2 = n2->left;
2757c478bd9Sstevel@tonic-gate 		/* create a key which will point to notice n2 */
2767c478bd9Sstevel@tonic-gate 		k2 = (struct key *)xmalloc(sizeof (struct key));
2777c478bd9Sstevel@tonic-gate 		k2->time = n2->time;
2787c478bd9Sstevel@tonic-gate 		k2->numnote = NLIM - NLIM/2;
2797c478bd9Sstevel@tonic-gate 		k2->notice = n2;
2807c478bd9Sstevel@tonic-gate 		k2->right = k;
2817c478bd9Sstevel@tonic-gate 		k2->left = k->left;
2827c478bd9Sstevel@tonic-gate 		k->left = k2;
2837c478bd9Sstevel@tonic-gate 		(k2->left)->right = k2;
2847c478bd9Sstevel@tonic-gate 		n2->key = k2;	/* have n2 point back to k2 */
2857c478bd9Sstevel@tonic-gate 		/* which of the new sublists will hold the new notice? */
2867c478bd9Sstevel@tonic-gate 		if (k2->time > time) k = k2; }
2877c478bd9Sstevel@tonic-gate 
288*e2553d68SSerge Dussud 	/*
289*e2553d68SSerge Dussud 	 * the new notice n is ready to be inserted
290*e2553d68SSerge Dussud 	 * k points to the appropriate sublist
291*e2553d68SSerge Dussud 	 */
2927c478bd9Sstevel@tonic-gate 	k->numnote = k->numnote + 1;
2937c478bd9Sstevel@tonic-gate 	n2 = k->notice;
2947c478bd9Sstevel@tonic-gate 	while (n2->time > time) n2 = n2->left;
2957c478bd9Sstevel@tonic-gate 	n->right = n2->right;
2967c478bd9Sstevel@tonic-gate 	n->left = n2;
2977c478bd9Sstevel@tonic-gate 	(n2->right)->left = n;
2987c478bd9Sstevel@tonic-gate 	n2->right = n;
2997c478bd9Sstevel@tonic-gate 
300*e2553d68SSerge Dussud 	if ((current == NULL) || (current->time > time))
301*e2553d68SSerge Dussud 		current = n;
302*e2553d68SSerge Dussud 
303*e2553d68SSerge Dussud 	return (0);
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 
307*e2553d68SSerge Dussud /* ******************** */
3087c478bd9Sstevel@tonic-gate void
3097c478bd9Sstevel@tonic-gate el_remove(id, flag)
310*e2553d68SSerge Dussud /* ******************** */
3117c478bd9Sstevel@tonic-gate int	id, flag;
3127c478bd9Sstevel@tonic-gate {
313*e2553d68SSerge Dussud 	/*
314*e2553d68SSerge Dussud 	 * remove finds notices n that need to be removed by traversing thru
315*e2553d68SSerge Dussud 	 * the notice list.  if n is the sole element of a sublist, the
316*e2553d68SSerge Dussud 	 * sublist is deleted.  if not, an adjacent sublist is merged with
317*e2553d68SSerge Dussud 	 * n's sublist, if that is possible.  after these checks, n is removed.
318*e2553d68SSerge Dussud 	 */
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	struct notice *n, *n2;
3217c478bd9Sstevel@tonic-gate 	struct key *k, *kl, *kr;
3227c478bd9Sstevel@tonic-gate 
323*e2553d68SSerge Dussud 	if ((index == NULL) || (current == NULL))
324*e2553d68SSerge Dussud 		return;
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	n = current;
3277c478bd9Sstevel@tonic-gate 	while (n != NULL) {
328*e2553d68SSerge Dussud 		while ((n != NULL) && ((n->isdummy) || (n->id != id)))
329*e2553d68SSerge Dussud 			n = n->right;
3307c478bd9Sstevel@tonic-gate 		if (n != NULL) {
3317c478bd9Sstevel@tonic-gate 			/* n should be deleted */
3327c478bd9Sstevel@tonic-gate 			if ((n->key != NULL) && ((n->key)->numnote == 1)) {
3337c478bd9Sstevel@tonic-gate 				/* n = sole element of a sublist */
3347c478bd9Sstevel@tonic-gate 				k = n->key;
3357c478bd9Sstevel@tonic-gate 				(k->left)->right = k->right;
3367c478bd9Sstevel@tonic-gate 				(k->right)->left = k->left;
337*e2553d68SSerge Dussud 				free(k);
338*e2553d68SSerge Dussud 			} else { if (n->key != NULL) {
3397c478bd9Sstevel@tonic-gate 					/* n has a key pointing to it */
3407c478bd9Sstevel@tonic-gate 					(n->left)->key = n->key;
3417c478bd9Sstevel@tonic-gate 					(n->key)->time = (n->left)->time;
3427c478bd9Sstevel@tonic-gate 					(n->key)->notice = n->left; }
3437c478bd9Sstevel@tonic-gate 				/* find the key that points to this sublist */
3447c478bd9Sstevel@tonic-gate 				n2 = n;
3457c478bd9Sstevel@tonic-gate 				while (n2->key == NULL) n2 = n2->right;
3467c478bd9Sstevel@tonic-gate 				k = n2->key;
3477c478bd9Sstevel@tonic-gate 				k->numnote = k->numnote - 1;
348*e2553d68SSerge Dussud 				/*
349*e2553d68SSerge Dussud 				 * check if two adjacent sublists can be merged
350*e2553d68SSerge Dussud 				 * first check left, then check right
351*e2553d68SSerge Dussud 				 */
3527c478bd9Sstevel@tonic-gate 				kl = k->left;
3537c478bd9Sstevel@tonic-gate 				kr = k->right;
3547c478bd9Sstevel@tonic-gate 				if ((!(kl->notice)->isdummy) &&
3557c478bd9Sstevel@tonic-gate 				    ((kl->numnote+k->numnote) <= NLIM)) {
3567c478bd9Sstevel@tonic-gate 					/* delete the key to the left */
3577c478bd9Sstevel@tonic-gate 					(kl->notice)->key = NULL;
3587c478bd9Sstevel@tonic-gate 					k->numnote += kl->numnote;
3597c478bd9Sstevel@tonic-gate 					(kl->left)->right = k;
3607c478bd9Sstevel@tonic-gate 					k->left = kl->left;
361*e2553d68SSerge Dussud 					free(kl);
362*e2553d68SSerge Dussud 				} else if ((!(k->notice)->isdummy) &&
363*e2553d68SSerge Dussud 					    ((kr->numnote+k->numnote)
364*e2553d68SSerge Dussud 					    <= NLIM)) {
3657c478bd9Sstevel@tonic-gate 					/* delete this key */
3667c478bd9Sstevel@tonic-gate 					(k->notice)->key = NULL;
3677c478bd9Sstevel@tonic-gate 					kr->numnote += k->numnote;
3687c478bd9Sstevel@tonic-gate 					(k->left)->right = kr;
3697c478bd9Sstevel@tonic-gate 					kr->left = k->left;
3707c478bd9Sstevel@tonic-gate 					free(k); }
3717c478bd9Sstevel@tonic-gate 				}
3727c478bd9Sstevel@tonic-gate 			/* delete n, then advance n down the list */
3737c478bd9Sstevel@tonic-gate 			(n->left)->right = n->right;
3747c478bd9Sstevel@tonic-gate 			(n->right)->left = n->left;
3757c478bd9Sstevel@tonic-gate 			n2 = n->right;
3767c478bd9Sstevel@tonic-gate 			free(n);
3777c478bd9Sstevel@tonic-gate 			n = n2;
3787c478bd9Sstevel@tonic-gate 			}
3797c478bd9Sstevel@tonic-gate 		if (flag) break;
3807c478bd9Sstevel@tonic-gate 		}
3817c478bd9Sstevel@tonic-gate 	/* now reset current */
3827c478bd9Sstevel@tonic-gate 	k = (index->key)->left;
3837c478bd9Sstevel@tonic-gate 	while (k->left != NULL) k = k->left;
3847c478bd9Sstevel@tonic-gate 	n = (k->notice)->right;
3857c478bd9Sstevel@tonic-gate 	while ((n != NULL) && (n->isdummy)) n = n->right;
3867c478bd9Sstevel@tonic-gate 	current = n;
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 
390*e2553d68SSerge Dussud /* ********************* */
391032624d5Sbasabi int
392032624d5Sbasabi el_empty(void)
393*e2553d68SSerge Dussud /* ********************* */
3947c478bd9Sstevel@tonic-gate {
395*e2553d68SSerge Dussud 	if (current == NULL)
396*e2553d68SSerge Dussud 		return (1);
397*e2553d68SSerge Dussud 	else
398*e2553d68SSerge Dussud 		return (0);
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 
402*e2553d68SSerge Dussud /* ********************* */
4037c478bd9Sstevel@tonic-gate void *
404032624d5Sbasabi el_first(void)
405*e2553d68SSerge Dussud /* ********************* */
4067c478bd9Sstevel@tonic-gate {
4077c478bd9Sstevel@tonic-gate 	struct notice *n, *fn;
4087c478bd9Sstevel@tonic-gate 	struct key *k, *fk;
4097c478bd9Sstevel@tonic-gate 	struct index *ind, *fi;
4107c478bd9Sstevel@tonic-gate 	int ctr, *val;
4117c478bd9Sstevel@tonic-gate 	time_t next_int;
4127c478bd9Sstevel@tonic-gate 
413*e2553d68SSerge Dussud 	if ((index == NULL) || (current == NULL))
414*e2553d68SSerge Dussud 		return (NULL);
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	while ((index->key)->time < current->time) {
4177c478bd9Sstevel@tonic-gate 		if (DU == 2) {
4187c478bd9Sstevel@tonic-gate 			/* only two intervals, so relabel first one */
4197c478bd9Sstevel@tonic-gate 			k = index->key;
4207c478bd9Sstevel@tonic-gate 			k->time += DT;
4217c478bd9Sstevel@tonic-gate 			(k->notice)->time += DT;
4227c478bd9Sstevel@tonic-gate 			continue; }
423*e2553d68SSerge Dussud 		/*
424*e2553d68SSerge Dussud 		 * remove the notice, key, and index corresponding
425*e2553d68SSerge Dussud 		 * to the first time interval.  Then split the
426*e2553d68SSerge Dussud 		 * overflow interval into a normal interval
427*e2553d68SSerge Dussud 		 * plus an overflow interval.
428*e2553d68SSerge Dussud 		 */
4297c478bd9Sstevel@tonic-gate 		fi = index;
4307c478bd9Sstevel@tonic-gate 		fk = fi->key;
4317c478bd9Sstevel@tonic-gate 		fn = fk->notice;
4327c478bd9Sstevel@tonic-gate 		(fn->left)->right = fn->right;
4337c478bd9Sstevel@tonic-gate 		(fn->right)->left = fn->left;
4347c478bd9Sstevel@tonic-gate 		(fk->left)->right = fk->right;
4357c478bd9Sstevel@tonic-gate 		(fk->right)->left = fk->left;
4367c478bd9Sstevel@tonic-gate 		index = index->right;
4377c478bd9Sstevel@tonic-gate 		/* find where to split	*/
4387c478bd9Sstevel@tonic-gate 		ind = index;
4397c478bd9Sstevel@tonic-gate 		while ((ind->right)->right != NULL) ind = ind->right;
4407c478bd9Sstevel@tonic-gate 		/* ind points to the next to last index interval	*/
4417c478bd9Sstevel@tonic-gate 		k = ind->key;
4427c478bd9Sstevel@tonic-gate 		next_int = k->time + DT;	/* upper bound on new inter.  */
4437c478bd9Sstevel@tonic-gate 		while (k->time < next_int) k = k->right;
4447c478bd9Sstevel@tonic-gate 		/* k points to the appropriate sublist of notices	*/
4457c478bd9Sstevel@tonic-gate 		n = (k->notice)->left;
4467c478bd9Sstevel@tonic-gate 		ctr = 1;
4477c478bd9Sstevel@tonic-gate 		while (n->time >= next_int) {
4487c478bd9Sstevel@tonic-gate 			ctr++;
4497c478bd9Sstevel@tonic-gate 			n = n->left; }
4507c478bd9Sstevel@tonic-gate 		n = n->right;
451*e2553d68SSerge Dussud 		/*
452*e2553d68SSerge Dussud 		 * n points to first notice of the new overflow interval
453*e2553d68SSerge Dussud 		 * ctr tells how many notices are in the first sublist
454*e2553d68SSerge Dussud 		 *	of the new overflow interval
455*e2553d68SSerge Dussud 		 * insert the new index element
456*e2553d68SSerge Dussud 		 */
4577c478bd9Sstevel@tonic-gate 		fi->right = ind->right;
4587c478bd9Sstevel@tonic-gate 		ind->right = fi;
4597c478bd9Sstevel@tonic-gate 		/* insert the new dummy key	*/
4607c478bd9Sstevel@tonic-gate 		fk->time = next_int;
4617c478bd9Sstevel@tonic-gate 		fk->numnote = k->numnote - ctr + 1;
4627c478bd9Sstevel@tonic-gate 		fk->left = k->left;
4637c478bd9Sstevel@tonic-gate 		fk->right = k;
4647c478bd9Sstevel@tonic-gate 		(k->left)->right = fk;
4657c478bd9Sstevel@tonic-gate 		k->left = fk;
4667c478bd9Sstevel@tonic-gate 		k->numnote = ctr;
4677c478bd9Sstevel@tonic-gate 		/* insert the new dummy notice	*/
4687c478bd9Sstevel@tonic-gate 		fn->time = next_int;
4697c478bd9Sstevel@tonic-gate 		fn->left = n->left;
4707c478bd9Sstevel@tonic-gate 		fn->right = n;
4717c478bd9Sstevel@tonic-gate 		(n->left)->right = fn;
4727c478bd9Sstevel@tonic-gate 		n->left = fn; }
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	/* remove the first element of the list */
4757c478bd9Sstevel@tonic-gate 	(current->left)->right = current->right;
4767c478bd9Sstevel@tonic-gate 	(current->right)->left = current->left;
4777c478bd9Sstevel@tonic-gate 	/* now update the numnote field in the appropriate key */
4787c478bd9Sstevel@tonic-gate 	n = current;
4797c478bd9Sstevel@tonic-gate 	while (n->key == NULL) n = n->right;
4807c478bd9Sstevel@tonic-gate 	k = n->key;
4817c478bd9Sstevel@tonic-gate 	k->numnote = k->numnote - 1;
4827c478bd9Sstevel@tonic-gate 	/* if numnote = 0 then this key must be removed */
4837c478bd9Sstevel@tonic-gate 	if (k->numnote == 0) {
4847c478bd9Sstevel@tonic-gate 		(k->left)->right = k->right;
4857c478bd9Sstevel@tonic-gate 		(k->right)->left = k->left;
4867c478bd9Sstevel@tonic-gate 		free(k); }
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	/* now set current to be the head of the list */
4897c478bd9Sstevel@tonic-gate 	fn = current->right;
4907c478bd9Sstevel@tonic-gate 	while ((fn != NULL) && (fn->isdummy))
4917c478bd9Sstevel@tonic-gate 		fn = fn->right;
4927c478bd9Sstevel@tonic-gate 	val = current->event;
4937c478bd9Sstevel@tonic-gate 	free(current);
4947c478bd9Sstevel@tonic-gate 	current = fn;
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	return (val);
4977c478bd9Sstevel@tonic-gate }
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 
500*e2553d68SSerge Dussud /* ************** */
5017c478bd9Sstevel@tonic-gate void
502032624d5Sbasabi el_delete(void)
503*e2553d68SSerge Dussud /* ************** */
5047c478bd9Sstevel@tonic-gate {
5057c478bd9Sstevel@tonic-gate 	/* el_delete frees up all the space associated with the event list */
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	struct index *ind, *ind2;
5087c478bd9Sstevel@tonic-gate 	struct key *k, *k2;
5097c478bd9Sstevel@tonic-gate 	struct notice *n, *n2;
5107c478bd9Sstevel@tonic-gate 
511*e2553d68SSerge Dussud 	if (index == NULL)
512*e2553d68SSerge Dussud 		return;
5137c478bd9Sstevel@tonic-gate 	ind = index;
5147c478bd9Sstevel@tonic-gate 	k = ind->key;
5157c478bd9Sstevel@tonic-gate 	while (k->left != NULL) k = k->left;
5167c478bd9Sstevel@tonic-gate 	n = k->notice;
5177c478bd9Sstevel@tonic-gate 	while (n != NULL) {
5187c478bd9Sstevel@tonic-gate 		n2 = n->right;
5197c478bd9Sstevel@tonic-gate 		free(n);
5207c478bd9Sstevel@tonic-gate 		n = n2; }
5217c478bd9Sstevel@tonic-gate 	while (k != NULL) {
5227c478bd9Sstevel@tonic-gate 		k2 = k->right;
5237c478bd9Sstevel@tonic-gate 		free(k);
5247c478bd9Sstevel@tonic-gate 		k = k2; }
5257c478bd9Sstevel@tonic-gate 	while (ind != NULL) {
5267c478bd9Sstevel@tonic-gate 		ind2 = ind->right;
5277c478bd9Sstevel@tonic-gate 		free(ind);
5287c478bd9Sstevel@tonic-gate 		ind = ind2; }
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	index = NULL;
5317c478bd9Sstevel@tonic-gate 	current = NULL;
5327c478bd9Sstevel@tonic-gate }
533