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