xref: /onnv-gate/usr/src/cmd/cron/elm.c (revision 7879:28e47ba3bea5)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7879SSerge.Dussud@Sun.COM  * Common Development and Distribution License (the "License").
6*7879SSerge.Dussud@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate 
22523Sbasabi /*
23*7879SSerge.Dussud@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24523Sbasabi  * Use is subject to license terms.
25523Sbasabi  */
26523Sbasabi 
270Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate 
310Sstevel@tonic-gate 
32*7879SSerge.Dussud@Sun.COM /* ********************************************************************** */
33*7879SSerge.Dussud@Sun.COM /* *		General-Purpose Event List Manager			* */
34*7879SSerge.Dussud@Sun.COM /* ********************************************************************** */
35*7879SSerge.Dussud@Sun.COM /*
36*7879SSerge.Dussud@Sun.COM  *	description:	These routines maintain a time-ordered list of events.
37*7879SSerge.Dussud@Sun.COM  *	functions available:
38*7879SSerge.Dussud@Sun.COM  *		init :	Creates and initializes the data structure.
39*7879SSerge.Dussud@Sun.COM  *			See the reference for parameters to init.
40*7879SSerge.Dussud@Sun.COM  *		add(&event, time, id) :	Adds an event to the list.
41*7879SSerge.Dussud@Sun.COM  *					Returns: 0 if success,
42*7879SSerge.Dussud@Sun.COM  *						-2 if event time is lower
43*7879SSerge.Dussud@Sun.COM  *						   than Lower Bound time LB
44*7879SSerge.Dussud@Sun.COM  *						-1 else
45*7879SSerge.Dussud@Sun.COM  *		remove(id) :	Removes events (with appropriate id).
46*7879SSerge.Dussud@Sun.COM  *		empty : Returns true if the list is empty, false otherwise.
47*7879SSerge.Dussud@Sun.COM  *		first :	Removes the element at the head of the list.
48*7879SSerge.Dussud@Sun.COM  *			Returns a pointer to the event.
49*7879SSerge.Dussud@Sun.COM  *		delete : Frees up all allocated storage associated
50*7879SSerge.Dussud@Sun.COM  *			 with the event list.
51*7879SSerge.Dussud@Sun.COM  *	reference:	Franta, W. R. and Maly, K.,
52*7879SSerge.Dussud@Sun.COM  *			"An efficient data structure for the
53*7879SSerge.Dussud@Sun.COM  *			simulation event set ", CACM Vol. 20(8),
54*7879SSerge.Dussud@Sun.COM  *			Aug 1977, pp. 596-602.
55*7879SSerge.Dussud@Sun.COM  *	machine dependant:	the constant INFINITY
56*7879SSerge.Dussud@Sun.COM  */
57*7879SSerge.Dussud@Sun.COM /* ********************************************************************** */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 
600Sstevel@tonic-gate #include <sys/types.h>
610Sstevel@tonic-gate #include <stdlib.h>
620Sstevel@tonic-gate 
630Sstevel@tonic-gate extern	void *xmalloc(size_t);
640Sstevel@tonic-gate 
650Sstevel@tonic-gate #define	INFINITY	2147483647L	/* upper bound on time	*/
66*7879SSerge.Dussud@Sun.COM #define	NULL		0		/* a null pointer 	*/
67*7879SSerge.Dussud@Sun.COM #define	TRUE		1
68*7879SSerge.Dussud@Sun.COM #define	FALSE		0
690Sstevel@tonic-gate 
700Sstevel@tonic-gate /* the following parameters are set in init	*/
710Sstevel@tonic-gate static int	DU;		/* number of time intervals	*/
720Sstevel@tonic-gate static time_t	LB;		/* lower bound on time	*/
730Sstevel@tonic-gate static time_t	DT;		/* width of interval	*/
740Sstevel@tonic-gate static int	NLIM;		/* max notices per sublist	*/
750Sstevel@tonic-gate 
76*7879SSerge.Dussud@Sun.COM /*
77*7879SSerge.Dussud@Sun.COM  * a notice points to an event.  a notice has the following fields:
78*7879SSerge.Dussud@Sun.COM  *	time = time of the event.
79*7879SSerge.Dussud@Sun.COM  *	id = identifier for an event or class of events that may need
80*7879SSerge.Dussud@Sun.COM  *		to be removed (other than at the front of the list).
81*7879SSerge.Dussud@Sun.COM  *	event = pointer to the event.
82*7879SSerge.Dussud@Sun.COM  *	isdummy = tells whether this notice points to a real event or
83*7879SSerge.Dussud@Sun.COM  *		is just a dummy notice (one that is used to "mark off"
84*7879SSerge.Dussud@Sun.COM  *		the time intervals that the user specifies in init).
85*7879SSerge.Dussud@Sun.COM  *	key = points back to the key that points to this notice,
86*7879SSerge.Dussud@Sun.COM  *		if there is one.
87*7879SSerge.Dussud@Sun.COM  *	left = points to the notice immediately preceding this one.
88*7879SSerge.Dussud@Sun.COM  *	right = points to the notice immediately following this one.
89*7879SSerge.Dussud@Sun.COM  */
900Sstevel@tonic-gate struct notice {	time_t	time;
910Sstevel@tonic-gate 		int	id;
920Sstevel@tonic-gate 		void	*event;
930Sstevel@tonic-gate 		short int	isdummy;
940Sstevel@tonic-gate 		struct key	*key;
950Sstevel@tonic-gate 		struct notice	*left;
960Sstevel@tonic-gate 		struct notice	*right; };
970Sstevel@tonic-gate 
980Sstevel@tonic-gate /* current points to the front of the list of notices (events)	*/
99*7879SSerge.Dussud@Sun.COM struct notice	*current = NULL;
100*7879SSerge.Dussud@Sun.COM 
101*7879SSerge.Dussud@Sun.COM /*
102*7879SSerge.Dussud@Sun.COM  * a key points to a sublist of notices.  a key has the following fields:
103*7879SSerge.Dussud@Sun.COM  *	time = max time of notices in sublist.
104*7879SSerge.Dussud@Sun.COM  *	numnote = number of notices in sublist.
105*7879SSerge.Dussud@Sun.COM  *	notice = pointer to the notice with max time.
106*7879SSerge.Dussud@Sun.COM  *	left = points to the key immediately preceding this one.
107*7879SSerge.Dussud@Sun.COM  *	right = points to the key immediately following this one.
108*7879SSerge.Dussud@Sun.COM  */
1090Sstevel@tonic-gate struct key {	time_t	time;
1100Sstevel@tonic-gate 		int	numnote;
1110Sstevel@tonic-gate 		struct notice	*notice;
1120Sstevel@tonic-gate 		struct key	*left;
1130Sstevel@tonic-gate 		struct key	*right; };
1140Sstevel@tonic-gate 
115*7879SSerge.Dussud@Sun.COM /*
116*7879SSerge.Dussud@Sun.COM  * the index list breaks the keys into time intervals as specified in init.
117*7879SSerge.Dussud@Sun.COM  * the index is "shifted" one time interval whenever el_first returns an
118*7879SSerge.Dussud@Sun.COM  * event with a time greater than the max time of the first interval
119*7879SSerge.Dussud@Sun.COM  * (eg. with intervals of a day which span one week (MTWTFSS),
120*7879SSerge.Dussud@Sun.COM  * if el_first finds the next event is on tuesday, then
121*7879SSerge.Dussud@Sun.COM  * the intervals of the event list get shifted (TWTFSSM).
122*7879SSerge.Dussud@Sun.COM  */
1230Sstevel@tonic-gate struct index {	struct key *key;
1240Sstevel@tonic-gate 		struct index *right; };
1250Sstevel@tonic-gate 
126*7879SSerge.Dussud@Sun.COM /* index pts to the front of the index list */
127*7879SSerge.Dussud@Sun.COM static struct index *index = NULL;
1280Sstevel@tonic-gate 
129*7879SSerge.Dussud@Sun.COM /* ******************* */
1300Sstevel@tonic-gate void
el_init(du,lb,dt,nlim)131*7879SSerge.Dussud@Sun.COM el_init(du, lb, dt, nlim)
132*7879SSerge.Dussud@Sun.COM /* ******************* */
1330Sstevel@tonic-gate int du, nlim;
1340Sstevel@tonic-gate time_t lb, dt;
1350Sstevel@tonic-gate {
1360Sstevel@tonic-gate 	int	i;
1370Sstevel@tonic-gate 	time_t	t;
138*7879SSerge.Dussud@Sun.COM 	struct index *indprev, *ind;
1390Sstevel@tonic-gate 	struct key *kprev, *k;
1400Sstevel@tonic-gate 	struct notice *nprev, *n;
1410Sstevel@tonic-gate 
142*7879SSerge.Dussud@Sun.COM 	if ((du < 1) || (dt < 1) || (nlim < 1))
143*7879SSerge.Dussud@Sun.COM 		return;
1440Sstevel@tonic-gate 	DU = du + 1;
1450Sstevel@tonic-gate 	LB = lb;
1460Sstevel@tonic-gate 	DT = dt;
1470Sstevel@tonic-gate 	NLIM = nlim;
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	/*
1500Sstevel@tonic-gate 	 * initialize index, keys, and notices
1510Sstevel@tonic-gate 	 */
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	/* create first dummy notice */
154*7879SSerge.Dussud@Sun.COM 	n = (struct notice *)xmalloc(sizeof (struct notice));
1550Sstevel@tonic-gate 	n->time = LB;
1560Sstevel@tonic-gate 	n->isdummy = TRUE;
1570Sstevel@tonic-gate 	n->left = NULL;
1580Sstevel@tonic-gate 	nprev = n;
1590Sstevel@tonic-gate 	/* create first dummy key */
160*7879SSerge.Dussud@Sun.COM 	k = (struct key *)xmalloc(sizeof (struct key));
1610Sstevel@tonic-gate 	k->time = LB;
1620Sstevel@tonic-gate 	k->numnote = 1;
1630Sstevel@tonic-gate 	k->notice = n;
1640Sstevel@tonic-gate 	k->left = NULL;
1650Sstevel@tonic-gate 	kprev = k;
1660Sstevel@tonic-gate 	/* make notice point to key */
1670Sstevel@tonic-gate 	n->key = k;
1680Sstevel@tonic-gate 	/* no index element to allocate this time */
1690Sstevel@tonic-gate 	indprev = NULL;
1700Sstevel@tonic-gate 	/* create dummy notices, dummy keys, and index elements */
1710Sstevel@tonic-gate 	t = LB;
172*7879SSerge.Dussud@Sun.COM 	for (i = 1; i < DU; i++) {
1730Sstevel@tonic-gate 		t = t + DT;
174*7879SSerge.Dussud@Sun.COM 		n = (struct notice *)xmalloc(sizeof (struct notice));
1750Sstevel@tonic-gate 		n->time = t;
1760Sstevel@tonic-gate 		n->isdummy = TRUE;
1770Sstevel@tonic-gate 		n->left = nprev;
1780Sstevel@tonic-gate 		nprev->right = n;
1790Sstevel@tonic-gate 		nprev = n;
180*7879SSerge.Dussud@Sun.COM 		k = (struct key *)xmalloc(sizeof (struct key));
1810Sstevel@tonic-gate 		k->time = t;
1820Sstevel@tonic-gate 		k->numnote = 1;
1830Sstevel@tonic-gate 		k->notice = n;
1840Sstevel@tonic-gate 		k->left = kprev;
1850Sstevel@tonic-gate 		kprev->right = k;
1860Sstevel@tonic-gate 		kprev = k;
1870Sstevel@tonic-gate 		n->key = k;
188*7879SSerge.Dussud@Sun.COM 		ind = (struct index *)xmalloc(sizeof (struct index));
1890Sstevel@tonic-gate 		ind->key = k;
190*7879SSerge.Dussud@Sun.COM 		if (indprev == NULL)
191*7879SSerge.Dussud@Sun.COM 			index = ind;
192*7879SSerge.Dussud@Sun.COM 		else
193*7879SSerge.Dussud@Sun.COM 			indprev->right = ind;
1940Sstevel@tonic-gate 		indprev = ind; }
1950Sstevel@tonic-gate 	/* create last dummy notice */
196*7879SSerge.Dussud@Sun.COM 	n = (struct notice *)xmalloc(sizeof (struct notice));
1970Sstevel@tonic-gate 	n->time = INFINITY;
1980Sstevel@tonic-gate 	n->isdummy = TRUE;
1990Sstevel@tonic-gate 	n->left = nprev;
2000Sstevel@tonic-gate 	n->right = NULL;
2010Sstevel@tonic-gate 	nprev->right = n;
2020Sstevel@tonic-gate 	/* create last dummy key */
203*7879SSerge.Dussud@Sun.COM 	k = (struct key *)xmalloc(sizeof (struct key));
2040Sstevel@tonic-gate 	k->time = INFINITY;
2050Sstevel@tonic-gate 	k->numnote = 1;
2060Sstevel@tonic-gate 	k->notice = n;
2070Sstevel@tonic-gate 	k->left = kprev;
2080Sstevel@tonic-gate 	k->right = NULL;
2090Sstevel@tonic-gate 	kprev->right = k;
2100Sstevel@tonic-gate 	n->key = k;
2110Sstevel@tonic-gate 	/* create last index element */
212*7879SSerge.Dussud@Sun.COM 	ind = (struct index *)xmalloc(sizeof (struct index));
2130Sstevel@tonic-gate 	ind->key = k;
2140Sstevel@tonic-gate 	ind->right = NULL;
2150Sstevel@tonic-gate 	indprev->right = ind;
216*7879SSerge.Dussud@Sun.COM 
2170Sstevel@tonic-gate 	current = NULL;
2180Sstevel@tonic-gate }
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 
221*7879SSerge.Dussud@Sun.COM /* ********************** */
222*7879SSerge.Dussud@Sun.COM int
el_add(event,time,id)223*7879SSerge.Dussud@Sun.COM el_add(event, time, id)
224*7879SSerge.Dussud@Sun.COM /* ********************** */
2250Sstevel@tonic-gate void	*event;
2260Sstevel@tonic-gate int	id;
2270Sstevel@tonic-gate time_t	time;
2280Sstevel@tonic-gate {
229*7879SSerge.Dussud@Sun.COM 	/*
230*7879SSerge.Dussud@Sun.COM 	 * add works slightly differently than in the reference.  if the
231*7879SSerge.Dussud@Sun.COM 	 * sublist to be inserted into is full (numnote = NLIM),
232*7879SSerge.Dussud@Sun.COM 	 * the sublist is split in half.  thus the size of the sublists
233*7879SSerge.Dussud@Sun.COM 	 * in this implementation normally ranges from NLIM/2 to NLIM.
234*7879SSerge.Dussud@Sun.COM 	 */
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	struct index *ind;
237*7879SSerge.Dussud@Sun.COM 	struct key *k, *k2;
238*7879SSerge.Dussud@Sun.COM 	struct notice *n, *n2;
2390Sstevel@tonic-gate 	int i;
2400Sstevel@tonic-gate 
241*7879SSerge.Dussud@Sun.COM 	/*
242*7879SSerge.Dussud@Sun.COM 	 * time may be 0 when set by next_time() on error or an
243*7879SSerge.Dussud@Sun.COM 	 * invalid time specification of job
244*7879SSerge.Dussud@Sun.COM 	 */
245*7879SSerge.Dussud@Sun.COM 	if ((index == NULL) || (time <= 0)) {
246*7879SSerge.Dussud@Sun.COM 		return (-1);
247*7879SSerge.Dussud@Sun.COM 	}
248*7879SSerge.Dussud@Sun.COM 	if (time < LB) {
249*7879SSerge.Dussud@Sun.COM 		return (-2);
250*7879SSerge.Dussud@Sun.COM 	}
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	/* allocate new notice */
253*7879SSerge.Dussud@Sun.COM 	n = (struct notice *)xmalloc(sizeof (struct notice));
2540Sstevel@tonic-gate 	n->time = time;
2550Sstevel@tonic-gate 	n->id = id;
2560Sstevel@tonic-gate 	n->event = event;
2570Sstevel@tonic-gate 	n->isdummy = FALSE;
2580Sstevel@tonic-gate 	n->key = NULL;
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	/* find the right interval */
2610Sstevel@tonic-gate 	ind = index;
2620Sstevel@tonic-gate 	while ((ind->key)->time <= time) ind = ind->right;
263*7879SSerge.Dussud@Sun.COM 
2640Sstevel@tonic-gate 	/* find the right key */
2650Sstevel@tonic-gate 	k = (ind->key)->left;
2660Sstevel@tonic-gate 	while (k->time > time) k = k->left;
2670Sstevel@tonic-gate 	k = k->right;
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	/* (k->time>time) and ((k->left)->time<=time) */
2700Sstevel@tonic-gate 	if (k->numnote == NLIM) {
2710Sstevel@tonic-gate 		/* k's sublist is full, so split it */
2720Sstevel@tonic-gate 		k->numnote = NLIM / 2;
2730Sstevel@tonic-gate 		n2 = k->notice;
274*7879SSerge.Dussud@Sun.COM 		for (i = 1; i <= NLIM/2; i++) n2 = n2->left;
2750Sstevel@tonic-gate 		/* create a key which will point to notice n2 */
276*7879SSerge.Dussud@Sun.COM 		k2 = (struct key *)xmalloc(sizeof (struct key));
2770Sstevel@tonic-gate 		k2->time = n2->time;
2780Sstevel@tonic-gate 		k2->numnote = NLIM - NLIM/2;
2790Sstevel@tonic-gate 		k2->notice = n2;
2800Sstevel@tonic-gate 		k2->right = k;
2810Sstevel@tonic-gate 		k2->left = k->left;
2820Sstevel@tonic-gate 		k->left = k2;
2830Sstevel@tonic-gate 		(k2->left)->right = k2;
2840Sstevel@tonic-gate 		n2->key = k2;	/* have n2 point back to k2 */
2850Sstevel@tonic-gate 		/* which of the new sublists will hold the new notice? */
2860Sstevel@tonic-gate 		if (k2->time > time) k = k2; }
2870Sstevel@tonic-gate 
288*7879SSerge.Dussud@Sun.COM 	/*
289*7879SSerge.Dussud@Sun.COM 	 * the new notice n is ready to be inserted
290*7879SSerge.Dussud@Sun.COM 	 * k points to the appropriate sublist
291*7879SSerge.Dussud@Sun.COM 	 */
2920Sstevel@tonic-gate 	k->numnote = k->numnote + 1;
2930Sstevel@tonic-gate 	n2 = k->notice;
2940Sstevel@tonic-gate 	while (n2->time > time) n2 = n2->left;
2950Sstevel@tonic-gate 	n->right = n2->right;
2960Sstevel@tonic-gate 	n->left = n2;
2970Sstevel@tonic-gate 	(n2->right)->left = n;
2980Sstevel@tonic-gate 	n2->right = n;
2990Sstevel@tonic-gate 
300*7879SSerge.Dussud@Sun.COM 	if ((current == NULL) || (current->time > time))
301*7879SSerge.Dussud@Sun.COM 		current = n;
302*7879SSerge.Dussud@Sun.COM 
303*7879SSerge.Dussud@Sun.COM 	return (0);
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 
307*7879SSerge.Dussud@Sun.COM /* ******************** */
3080Sstevel@tonic-gate void
el_remove(id,flag)309*7879SSerge.Dussud@Sun.COM el_remove(id, flag)
310*7879SSerge.Dussud@Sun.COM /* ******************** */
311*7879SSerge.Dussud@Sun.COM int	id, flag;
3120Sstevel@tonic-gate {
313*7879SSerge.Dussud@Sun.COM 	/*
314*7879SSerge.Dussud@Sun.COM 	 * remove finds notices n that need to be removed by traversing thru
315*7879SSerge.Dussud@Sun.COM 	 * the notice list.  if n is the sole element of a sublist, the
316*7879SSerge.Dussud@Sun.COM 	 * sublist is deleted.  if not, an adjacent sublist is merged with
317*7879SSerge.Dussud@Sun.COM 	 * n's sublist, if that is possible.  after these checks, n is removed.
318*7879SSerge.Dussud@Sun.COM 	 */
3190Sstevel@tonic-gate 
320*7879SSerge.Dussud@Sun.COM 	struct notice *n, *n2;
321*7879SSerge.Dussud@Sun.COM 	struct key *k, *kl, *kr;
3220Sstevel@tonic-gate 
323*7879SSerge.Dussud@Sun.COM 	if ((index == NULL) || (current == NULL))
324*7879SSerge.Dussud@Sun.COM 		return;
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	n = current;
327*7879SSerge.Dussud@Sun.COM 	while (n != NULL) {
328*7879SSerge.Dussud@Sun.COM 		while ((n != NULL) && ((n->isdummy) || (n->id != id)))
329*7879SSerge.Dussud@Sun.COM 			n = n->right;
3300Sstevel@tonic-gate 		if (n != NULL) {
3310Sstevel@tonic-gate 			/* n should be deleted */
332*7879SSerge.Dussud@Sun.COM 			if ((n->key != NULL) && ((n->key)->numnote == 1)) {
3330Sstevel@tonic-gate 				/* n = sole element of a sublist */
3340Sstevel@tonic-gate 				k = n->key;
3350Sstevel@tonic-gate 				(k->left)->right = k->right;
3360Sstevel@tonic-gate 				(k->right)->left = k->left;
337*7879SSerge.Dussud@Sun.COM 				free(k);
338*7879SSerge.Dussud@Sun.COM 			} else { if (n->key != NULL) {
3390Sstevel@tonic-gate 					/* n has a key pointing to it */
3400Sstevel@tonic-gate 					(n->left)->key = n->key;
3410Sstevel@tonic-gate 					(n->key)->time = (n->left)->time;
3420Sstevel@tonic-gate 					(n->key)->notice = n->left; }
3430Sstevel@tonic-gate 				/* find the key that points to this sublist */
3440Sstevel@tonic-gate 				n2 = n;
3450Sstevel@tonic-gate 				while (n2->key == NULL) n2 = n2->right;
3460Sstevel@tonic-gate 				k = n2->key;
3470Sstevel@tonic-gate 				k->numnote = k->numnote - 1;
348*7879SSerge.Dussud@Sun.COM 				/*
349*7879SSerge.Dussud@Sun.COM 				 * check if two adjacent sublists can be merged
350*7879SSerge.Dussud@Sun.COM 				 * first check left, then check right
351*7879SSerge.Dussud@Sun.COM 				 */
3520Sstevel@tonic-gate 				kl = k->left;
3530Sstevel@tonic-gate 				kr = k->right;
354*7879SSerge.Dussud@Sun.COM 				if ((!(kl->notice)->isdummy) &&
355*7879SSerge.Dussud@Sun.COM 				    ((kl->numnote+k->numnote) <= NLIM)) {
3560Sstevel@tonic-gate 					/* delete the key to the left */
3570Sstevel@tonic-gate 					(kl->notice)->key = NULL;
3580Sstevel@tonic-gate 					k->numnote += kl->numnote;
3590Sstevel@tonic-gate 					(kl->left)->right = k;
3600Sstevel@tonic-gate 					k->left = kl->left;
361*7879SSerge.Dussud@Sun.COM 					free(kl);
362*7879SSerge.Dussud@Sun.COM 				} else if ((!(k->notice)->isdummy) &&
363*7879SSerge.Dussud@Sun.COM 					    ((kr->numnote+k->numnote)
364*7879SSerge.Dussud@Sun.COM 					    <= NLIM)) {
3650Sstevel@tonic-gate 					/* delete this key */
3660Sstevel@tonic-gate 					(k->notice)->key = NULL;
3670Sstevel@tonic-gate 					kr->numnote += k->numnote;
3680Sstevel@tonic-gate 					(k->left)->right = kr;
3690Sstevel@tonic-gate 					kr->left = k->left;
3700Sstevel@tonic-gate 					free(k); }
3710Sstevel@tonic-gate 				}
3720Sstevel@tonic-gate 			/* delete n, then advance n down the list */
3730Sstevel@tonic-gate 			(n->left)->right = n->right;
3740Sstevel@tonic-gate 			(n->right)->left = n->left;
3750Sstevel@tonic-gate 			n2 = n->right;
3760Sstevel@tonic-gate 			free(n);
3770Sstevel@tonic-gate 			n = n2;
3780Sstevel@tonic-gate 			}
3790Sstevel@tonic-gate 		if (flag) break;
3800Sstevel@tonic-gate 		}
3810Sstevel@tonic-gate 	/* now reset current */
3820Sstevel@tonic-gate 	k = (index->key)->left;
3830Sstevel@tonic-gate 	while (k->left != NULL) k = k->left;
3840Sstevel@tonic-gate 	n = (k->notice)->right;
385*7879SSerge.Dussud@Sun.COM 	while ((n != NULL) && (n->isdummy)) n = n->right;
3860Sstevel@tonic-gate 	current = n;
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 
390*7879SSerge.Dussud@Sun.COM /* ********************* */
391523Sbasabi int
el_empty(void)392523Sbasabi el_empty(void)
393*7879SSerge.Dussud@Sun.COM /* ********************* */
3940Sstevel@tonic-gate {
395*7879SSerge.Dussud@Sun.COM 	if (current == NULL)
396*7879SSerge.Dussud@Sun.COM 		return (1);
397*7879SSerge.Dussud@Sun.COM 	else
398*7879SSerge.Dussud@Sun.COM 		return (0);
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 
402*7879SSerge.Dussud@Sun.COM /* ********************* */
4030Sstevel@tonic-gate void *
el_first(void)404523Sbasabi el_first(void)
405*7879SSerge.Dussud@Sun.COM /* ********************* */
4060Sstevel@tonic-gate {
407*7879SSerge.Dussud@Sun.COM 	struct notice *n, *fn;
408*7879SSerge.Dussud@Sun.COM 	struct key *k, *fk;
409*7879SSerge.Dussud@Sun.COM 	struct index *ind, *fi;
410*7879SSerge.Dussud@Sun.COM 	int ctr, *val;
4110Sstevel@tonic-gate 	time_t next_int;
4120Sstevel@tonic-gate 
413*7879SSerge.Dussud@Sun.COM 	if ((index == NULL) || (current == NULL))
414*7879SSerge.Dussud@Sun.COM 		return (NULL);
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	while ((index->key)->time < current->time) {
4170Sstevel@tonic-gate 		if (DU == 2) {
4180Sstevel@tonic-gate 			/* only two intervals, so relabel first one */
4190Sstevel@tonic-gate 			k = index->key;
4200Sstevel@tonic-gate 			k->time += DT;
4210Sstevel@tonic-gate 			(k->notice)->time += DT;
4220Sstevel@tonic-gate 			continue; }
423*7879SSerge.Dussud@Sun.COM 		/*
424*7879SSerge.Dussud@Sun.COM 		 * remove the notice, key, and index corresponding
425*7879SSerge.Dussud@Sun.COM 		 * to the first time interval.  Then split the
426*7879SSerge.Dussud@Sun.COM 		 * overflow interval into a normal interval
427*7879SSerge.Dussud@Sun.COM 		 * plus an overflow interval.
428*7879SSerge.Dussud@Sun.COM 		 */
4290Sstevel@tonic-gate 		fi = index;
4300Sstevel@tonic-gate 		fk = fi->key;
4310Sstevel@tonic-gate 		fn = fk->notice;
4320Sstevel@tonic-gate 		(fn->left)->right = fn->right;
4330Sstevel@tonic-gate 		(fn->right)->left = fn->left;
4340Sstevel@tonic-gate 		(fk->left)->right = fk->right;
4350Sstevel@tonic-gate 		(fk->right)->left = fk->left;
4360Sstevel@tonic-gate 		index = index->right;
4370Sstevel@tonic-gate 		/* find where to split	*/
4380Sstevel@tonic-gate 		ind = index;
4390Sstevel@tonic-gate 		while ((ind->right)->right != NULL) ind = ind->right;
4400Sstevel@tonic-gate 		/* ind points to the next to last index interval	*/
4410Sstevel@tonic-gate 		k = ind->key;
4420Sstevel@tonic-gate 		next_int = k->time + DT;	/* upper bound on new inter.  */
4430Sstevel@tonic-gate 		while (k->time < next_int) k = k->right;
4440Sstevel@tonic-gate 		/* k points to the appropriate sublist of notices	*/
4450Sstevel@tonic-gate 		n = (k->notice)->left;
4460Sstevel@tonic-gate 		ctr = 1;
4470Sstevel@tonic-gate 		while (n->time >= next_int) {
4480Sstevel@tonic-gate 			ctr++;
4490Sstevel@tonic-gate 			n = n->left; }
4500Sstevel@tonic-gate 		n = n->right;
451*7879SSerge.Dussud@Sun.COM 		/*
452*7879SSerge.Dussud@Sun.COM 		 * n points to first notice of the new overflow interval
453*7879SSerge.Dussud@Sun.COM 		 * ctr tells how many notices are in the first sublist
454*7879SSerge.Dussud@Sun.COM 		 *	of the new overflow interval
455*7879SSerge.Dussud@Sun.COM 		 * insert the new index element
456*7879SSerge.Dussud@Sun.COM 		 */
4570Sstevel@tonic-gate 		fi->right = ind->right;
4580Sstevel@tonic-gate 		ind->right = fi;
4590Sstevel@tonic-gate 		/* insert the new dummy key	*/
4600Sstevel@tonic-gate 		fk->time = next_int;
4610Sstevel@tonic-gate 		fk->numnote = k->numnote - ctr + 1;
4620Sstevel@tonic-gate 		fk->left = k->left;
4630Sstevel@tonic-gate 		fk->right = k;
4640Sstevel@tonic-gate 		(k->left)->right = fk;
4650Sstevel@tonic-gate 		k->left = fk;
4660Sstevel@tonic-gate 		k->numnote = ctr;
4670Sstevel@tonic-gate 		/* insert the new dummy notice	*/
4680Sstevel@tonic-gate 		fn->time = next_int;
4690Sstevel@tonic-gate 		fn->left = n->left;
4700Sstevel@tonic-gate 		fn->right = n;
4710Sstevel@tonic-gate 		(n->left)->right = fn;
4720Sstevel@tonic-gate 		n->left = fn; }
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 	/* remove the first element of the list */
4750Sstevel@tonic-gate 	(current->left)->right = current->right;
4760Sstevel@tonic-gate 	(current->right)->left = current->left;
4770Sstevel@tonic-gate 	/* now update the numnote field in the appropriate key */
4780Sstevel@tonic-gate 	n = current;
479*7879SSerge.Dussud@Sun.COM 	while (n->key == NULL) n = n->right;
4800Sstevel@tonic-gate 	k = n->key;
4810Sstevel@tonic-gate 	k->numnote = k->numnote - 1;
4820Sstevel@tonic-gate 	/* if numnote = 0 then this key must be removed */
4830Sstevel@tonic-gate 	if (k->numnote == 0) {
4840Sstevel@tonic-gate 		(k->left)->right = k->right;
485*7879SSerge.Dussud@Sun.COM 		(k->right)->left = k->left;
4860Sstevel@tonic-gate 		free(k); }
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 	/* now set current to be the head of the list */
4890Sstevel@tonic-gate 	fn = current->right;
490*7879SSerge.Dussud@Sun.COM 	while ((fn != NULL) && (fn->isdummy))
4910Sstevel@tonic-gate 		fn = fn->right;
4920Sstevel@tonic-gate 	val = current->event;
4930Sstevel@tonic-gate 	free(current);
4940Sstevel@tonic-gate 	current = fn;
4950Sstevel@tonic-gate 
496*7879SSerge.Dussud@Sun.COM 	return (val);
4970Sstevel@tonic-gate }
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 
500*7879SSerge.Dussud@Sun.COM /* ************** */
5010Sstevel@tonic-gate void
el_delete(void)502523Sbasabi el_delete(void)
503*7879SSerge.Dussud@Sun.COM /* ************** */
5040Sstevel@tonic-gate {
5050Sstevel@tonic-gate 	/* el_delete frees up all the space associated with the event list */
5060Sstevel@tonic-gate 
507*7879SSerge.Dussud@Sun.COM 	struct index *ind, *ind2;
508*7879SSerge.Dussud@Sun.COM 	struct key *k, *k2;
509*7879SSerge.Dussud@Sun.COM 	struct notice *n, *n2;
510*7879SSerge.Dussud@Sun.COM 
511*7879SSerge.Dussud@Sun.COM 	if (index == NULL)
512*7879SSerge.Dussud@Sun.COM 		return;
5130Sstevel@tonic-gate 	ind = index;
5140Sstevel@tonic-gate 	k = ind->key;
5150Sstevel@tonic-gate 	while (k->left != NULL) k = k->left;
5160Sstevel@tonic-gate 	n = k->notice;
517*7879SSerge.Dussud@Sun.COM 	while (n != NULL) {
5180Sstevel@tonic-gate 		n2 = n->right;
5190Sstevel@tonic-gate 		free(n);
5200Sstevel@tonic-gate 		n = n2; }
521*7879SSerge.Dussud@Sun.COM 	while (k != NULL) {
5220Sstevel@tonic-gate 		k2 = k->right;
5230Sstevel@tonic-gate 		free(k);
5240Sstevel@tonic-gate 		k = k2; }
525*7879SSerge.Dussud@Sun.COM 	while (ind != NULL) {
5260Sstevel@tonic-gate 		ind2 = ind->right;
5270Sstevel@tonic-gate 		free(ind);
5280Sstevel@tonic-gate 		ind = ind2; }
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	index = NULL;
5310Sstevel@tonic-gate 	current = NULL;
5320Sstevel@tonic-gate }
533