cdesktopenv/cde/programs/dtcm/server/reminder.c

999 lines
22 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $XConsortium: reminder.c /main/4 1995/11/09 12:48:20 rswiston $ */
/*
* (c) Copyright 1993, 1994 Hewlett-Packard Company
* (c) Copyright 1993, 1994 International Business Machines Corp.
* (c) Copyright 1993, 1994 Novell, Inc.
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
*/
#include <EUSCompat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "cmscalendar.h"
#include "reminder.h"
#include "appt4.h"
#include "repeat.h"
#include "v4ops.h"
#include "v5ops.h"
#include "rerule.h"
#include "reutil.h"
#include "iso8601.h"
/******************************************************************************
* forward declaration of static functions used within the file
******************************************************************************/
static _DtCmsRemInfo *_BuildReminder4Entry(
cms_entry *entry,
int aindex,
List_node *lnode,
time_t cutoff,
_DtCmsRemInfo **active);
static void _InsertReminder(
_DtCmsRemInfo **head,
_DtCmsRemInfo *rem);
static CSA_return_code _GetNextReminders(
_DtCmsRemQueue *remq,
time_t tick,
cms_reminder_ref **rems);
static CSA_return_code _GetNextRemindersFromQ(
_DtCmsRemQueue *remq,
int qindex,
time_t tick,
cms_reminder_ref **rems);
static cms_reminder_ref *_GetReminderRefFromInfo(
_DtCmsRemInfo *rem,
time_t starttime,
time_t runtime);
static void _RemoveReminderFromQ(
_DtCmsRemQueue *remq,
int qindex,
cms_entry *entry,
List_node *lnode,
time_t starttime,
boolean_t delfwd);
static _DtCmsRemInfo *_RemoveReminderFromList(
_DtCmsRemInfo **remq,
cms_entry *entry,
time_t starttime,
boolean_t delfwd);
static long _GetNextActiveTick(
cms_entry *entry,
time_t target,
time_t lasttick,
RepeatEvent *re);
static void _UpdateReminderQ(_DtCmsRemQueue *remq, int qindex);
static CSA_return_code _GetNextRemindersFromList(
_DtCmsRemInfo *rlist,
time_t giventime,
cms_reminder_ref **rf_r);
static void _DtCmsAddReminder4EntryToQ(
_DtCmsRemQueue *remq,
cms_entry *entry,
int aindex,
List_node *lnode);
/*****************************************************************************
* extern functions used in the library
*****************************************************************************/
extern void
_DtCmsAddReminderV4(Rm_que **qhead, Rm_que *p_reminder)
{
Rm_que *p_prev;
Rm_que *p_node;
if (p_reminder == NULL)
return;
p_prev = NULL;
p_node = *qhead;
while (p_node != NULL)
{
if (p_reminder->remind_at < p_node->remind_at)
break;
p_prev = p_node;
p_node = p_node->next;
}
if (p_prev == NULL) {
p_reminder->next = *qhead;
*qhead = p_reminder;
} else {
p_reminder->next = p_prev->next;
p_prev->next = p_reminder;
}
}
extern Rm_que *
_DtCmsRemoveReminderV4(Rm_que **qhead, Rm_que *p_prev, Rm_que *p_curr)
{
if (p_prev == NULL)
*qhead = p_curr->next;
else
p_prev->next = p_curr->next;
return (p_curr->next);
}
extern Rm_que *
build_reminder(
time_t current_time,
Appt_4 *p_appt,
Attr_4 p_attr,
time_t start_tick,
u_int start_ord)
{
int ntimes;
Period_4 period;
Rm_que *p_reminder = NULL;
/* Ignore the expired or unqualified reminder. */
p_reminder = NULL;
if (is_appointment(p_appt)) {
/* The event is not expired yet, build the reminder */
if (start_tick >= current_time)
{
if ((p_reminder = (Rm_que *)calloc(1, sizeof(Rm_que)))
== NULL)
return (NULL);
p_reminder->remind_ord = 0;
}
} else {
period = p_appt->period;
ntimes = _DtCms_get_ninstance_v4(p_appt);
while (start_ord <= ntimes) {
/* Event is not expired */
if (start_tick >= current_time) {
/* Event is not cancelled */
if (!_DtCms_marked_4_cancellation (p_appt, start_ord))
{
if ((p_reminder = (Rm_que *)calloc(1,
sizeof(Rm_que))) == NULL)
return (NULL);
p_reminder->remind_ord = start_ord;
break;
}
}
/* Event is expired, advance to next event */
start_tick = _DtCms_next_tick_v4 (start_tick, period);
start_ord++;
}
}
if (p_reminder != NULL) {
p_reminder->remind_at = start_tick;
p_reminder->appt = p_appt;
p_reminder->attr = p_attr;
}
return (p_reminder);
}
extern Reminder_4 *
_DtCmsGetReminderInfoV4(Rm_que *original)
{
Reminder_4 *copy;
if (original == NULL)
return (NULL);
if ((copy = calloc(1, sizeof(Reminder_4))) != NULL) {
copy->tick = original->remind_at;
copy->next = NULL;
if ((copy->attr.attr = strdup(original->attr->attr)) == NULL) {
free(copy);
return (NULL);
}
if ((copy->attr.value = strdup(original->attr->value)) == NULL)
{
_DtCm_free_reminder4(copy);
return (NULL);
}
if ((copy->attr.clientdata = strdup(original->attr->clientdata))
== NULL) {
_DtCm_free_reminder4(copy);
return (NULL);
}
copy->attr.next = NULL;
copy->appt_id.tick = copy->tick + atol (copy->attr.value);
copy->appt_id.key = original->appt->appt_id.key;
}
return (copy);
}
extern void
_DtCmsPrintReminderListV4(Rm_que *qhead)
{
Rm_que *p_node = qhead;
char *temp=NULL;
if (qhead == NULL)
return;
fprintf (stderr, "--- Active Reminder Queue ---\n");
while (p_node != NULL) {
if (temp = strchr(p_node->appt->what, '\n'))
*temp = '\0';
fprintf(stderr, "%s (%d) %s: %s\n", ctime(&p_node->remind_at),
p_node->remind_ord, p_node->attr->attr,
p_node->appt->what);
if (temp)
*temp = '\n';
p_node = p_node->next;
}
}
/*
* Obsolete all reminders (iff ord == 0) whose parent appointment matches a
* given appointment. If ord != 0, then obsolete all active reminders whose
* serving ordinal matches ord in additional to the matching of its parent
* appointment. The reminder of the next available instance will be put on the
* reminder queue.
*/
extern void
_DtCmsObsoleteReminderV4(
Rm_que **qhead,
Appt_4 *p_appt,
int ord,
boolean_t delforward)
{
Rm_que *p_prev;
Rm_que *p_next;
Rm_que *p_node;
Rm_que *p_hdr = NULL;
p_prev = NULL;
p_node = *qhead;
while (p_node != NULL) {
if ((p_node->appt != p_appt) ||
((ord != 0) && (ord != p_node->remind_ord)) ||
((ord != 0) && delforward && p_node->remind_ord < ord)) {
p_next = p_node->next;
} else {
/* Found the obsolete reminder. */
p_next = _DtCmsRemoveReminderV4 (qhead,p_prev,p_node);
if (ord == 0)
free (p_node);
else {
/* Chain the obsolete reminders together to
* re-calculate the new reminders.
*/
p_node->next = p_hdr;
p_hdr = p_node;
}
p_node = p_prev;
}
p_prev = p_node;
p_node = p_next;
}
/* Build the reminders of the next instance from obsoleted reminders.
* Note, we can't put this code in the above 'while'-loop because it
* may confuse the loop.
*/
while (p_hdr != NULL) {
p_next = p_hdr->next;
p_node = build_reminder(p_hdr->remind_at+1,
p_hdr->appt, p_hdr->attr,
p_hdr->remind_at, ord);
_DtCmsAddReminderV4 (qhead, p_node);
free (p_hdr);
p_hdr = p_next;
}
}
#define _DtCms_NUM_REMINDERS 4
extern void
_DtCmsAddReminders4Entry(
_DtCmsRemQueue **remq,
cms_entry *entry,
List_node *lnode)
{
_DtCmsRemQueue *queue;
int i;
if (*remq == NULL) {
if ((queue = (_DtCmsRemQueue *)calloc(1,
sizeof(_DtCmsRemQueue))) == NULL)
return;
/* initialize queues for the cde defined reminders */
if ((queue->aindex = (int *)malloc(sizeof(int) *
_DtCms_NUM_REMINDERS)) == NULL) {
free(queue);
return;
}
if ((queue->names = (char **)malloc(sizeof(char *) *
_DtCms_NUM_REMINDERS)) == NULL) {
free(queue->aindex);
free(queue);
return;
}
if ((queue->active = (_DtCmsRemInfo **)calloc(1,
sizeof(_DtCmsRemInfo) * _DtCms_NUM_REMINDERS)) == NULL) {
free(queue->names);
free(queue->aindex);
free(queue);
return;
}
if ((queue->oldhead = (_DtCmsRemInfo **)calloc(1,
sizeof(_DtCmsRemInfo) * _DtCms_NUM_REMINDERS)) == NULL) {
free(queue->active);
free(queue->names);
free(queue->aindex);
free(queue);
return;
}
queue->num_queues = _DtCms_NUM_REMINDERS;
queue->aindex[0] = CSA_ENTRY_ATTR_AUDIO_REMINDER_I;
queue->names[0] = CSA_ENTRY_ATTR_AUDIO_REMINDER;
queue->aindex[1] = CSA_ENTRY_ATTR_FLASHING_REMINDER_I;
queue->names[1] = CSA_ENTRY_ATTR_FLASHING_REMINDER;
queue->aindex[2] = CSA_ENTRY_ATTR_MAIL_REMINDER_I;
queue->names[2] = CSA_ENTRY_ATTR_MAIL_REMINDER;
queue->aindex[3] = CSA_ENTRY_ATTR_POPUP_REMINDER_I;
queue->names[3] = CSA_ENTRY_ATTR_POPUP_REMINDER;
/* set cutoff to be half an hour earlier than now
* to compensate time difference between machines
*/
queue->cutoff = time(0) - 60 * 30;
*remq = queue;
}
/* Add the qualified reminder attrs to the reminder queue */
for (i = 1; i <= entry->num_attrs; i++) {
if (entry->attrs[i].value == NULL ||
entry->attrs[i].value->type != CSA_VALUE_REMINDER)
continue;
_DtCmsAddReminder4EntryToQ(*remq, entry, i, lnode);
}
}
extern void
_DtCmsObsoleteReminder4Entry(
_DtCmsRemQueue *remq,
cms_entry *entry,
List_node *lnode,
time_t starttime,
boolean_t delfwd)
{
int i;
for (i = 0; i < remq->num_queues; i++) {
if (entry->attrs[remq->aindex[i]].value)
_RemoveReminderFromQ(remq, i, entry, lnode,
starttime, delfwd);
}
}
extern CSA_return_code
_DtCmsLookupReminder(
_DtCmsRemQueue *remq,
time_t tick,
uint num_names,
cms_attr_name *names,
cms_reminder_ref **rems)
{
int i, j;
CSA_return_code stat;
*rems = NULL;
if (remq == NULL)
return (CSA_SUCCESS);
if (num_names == 0)
return (_GetNextReminders(remq, tick, rems));
for (i = 0; i < num_names; i++) {
for (j = 0; j < remq->num_queues; j++) {
if (strcmp(names[i].name, remq->names[j]) == 0) {
names[i].num = remq->aindex[j];
if ((stat = _GetNextRemindersFromQ(remq, i,
tick, rems)) != CSA_SUCCESS) {
if (*rems)
_DtCmsFreeReminderRef(*rems);
return (stat);
}
}
}
}
return (CSA_SUCCESS);
}
extern void
_DtCmsFreeReminderRef(cms_reminder_ref *rems)
{
cms_reminder_ref *next;
while (rems != NULL) {
next = rems->next;
if (rems->reminder_name)
free(rems->reminder_name);
if (rems->entryid)
free(rems->entryid);
free(rems);
rems = next;
}
}
extern void
_DtCmsUpdateReminders(_DtCmsRemQueue *remq)
{
int i;
remq->cutoff = time(0) - 60*30;
for (i = 0; i < remq->num_queues; i++)
_UpdateReminderQ(remq, i);
}
/*****************************************************************************
* static functions used within the file
*****************************************************************************/
static _DtCmsRemInfo *
_BuildReminder4Entry(
cms_entry *entry,
int aindex,
List_node *lnode,
time_t cutoff,
_DtCmsRemInfo **active)
{
_DtCmsRemInfo *rptr, *rptr2;
time_t lead;
time_t tick;
RepeatEventState *restate;
if (active) *active = NULL;
if ((rptr = (_DtCmsRemInfo *)calloc(1, sizeof(_DtCmsRemInfo))) == NULL)
return (NULL);
rptr->lnode = lnode;
rptr->isentry = B_TRUE;
rptr->data.e = entry;
rptr->rem.i = entry->attrs[aindex].name.num;
_csa_iso8601_to_duration(entry->attrs[aindex].value->item.\
reminder_value->lead_time, &lead);
if (lnode == NULL) {
rptr->starttime = entry->key.time;
rptr->runtime = entry->key.time - lead;
} else {
if (lnode->lasttick == 0) {
lnode->lasttick = LastTick(entry->key.time, lnode->re);
lnode->duration = _DtCmsGetDuration(entry);
}
rptr->lasttick = lnode->lasttick;
/* calculate first tick */
tick = _GetNextActiveTick(entry, entry->key.time,
lnode->lasttick, lnode->re);
rptr->starttime = tick;
rptr->runtime = tick - lead;
/* need to calculate the active tick if
* 1. runtime of first tick is before cutoff time,
* 2. runtime of last tick is after cutoff time, and
* 3. there's reminders for instances after the cutoff time
*/
if (active && rptr->runtime < cutoff &&
(lnode->lasttick - lead >= cutoff) &&
(tick = _GetNextActiveTick(entry, cutoff + lead,
lnode->lasttick, lnode->re)) > 0)
{
if ((rptr2 = (_DtCmsRemInfo *)calloc(1,
sizeof(_DtCmsRemInfo))) == NULL) {
free(rptr);
return (NULL);
}
rptr2->lnode = lnode;
rptr2->isentry = B_TRUE;
rptr2->data.e = entry;
rptr2->rem.i = entry->attrs[aindex].name.num;
rptr2->lasttick = lnode->lasttick;
rptr2->starttime = tick;
rptr2->runtime = tick - lead;
*active = rptr2;
}
}
return (rptr);
}
static void
_InsertReminder(
_DtCmsRemInfo **head,
_DtCmsRemInfo *rem)
{
_DtCmsRemInfo *rptr, *prev;
for (rptr = *head, prev = NULL; rptr != NULL;
prev = rptr, rptr = rptr->next) {
if (rem->runtime < rptr->runtime)
break;
}
if (rptr == NULL) {
if (*head == NULL) {
*head = rem;
} else
prev->next = rem;
} else {
rem->next = rptr;
if (prev == NULL)
*head = rem;
else
prev->next = rem;
}
}
static CSA_return_code
_GetNextReminders(_DtCmsRemQueue *remq, time_t tick, cms_reminder_ref **rems)
{
CSA_return_code stat;
cms_reminder_ref *rptr, *head, *tail;
int i;
for (i = 0, head = NULL; i < remq->num_queues; i++) {
rptr = NULL;
if ((stat = _GetNextRemindersFromQ(remq, i, tick, &rptr))
!= CSA_SUCCESS) {
if (head)
_DtCmsFreeReminderRef(head);
return (stat);
}
if (rptr == NULL)
continue;
if (head == NULL)
head = tail = rptr;
else if (rptr->runtime == head->runtime) {
/* combine the list */
for (; tail->next != NULL; tail = tail->next);
tail->next = rptr;
tail = rptr;
} else if (rptr->runtime < head->runtime) {
_DtCmsFreeReminderRef(head);
head = tail = rptr;
} else
_DtCmsFreeReminderRef(rptr);
}
if (head) {
*rems = head;
}
return (CSA_SUCCESS);
}
static CSA_return_code
_GetNextRemindersFromQ(
_DtCmsRemQueue *remq,
int qindex,
time_t tick,
cms_reminder_ref **rems)
{
CSA_return_code stat;
cms_reminder_ref *rem = *rems;
if (tick >= remq->cutoff)
return (_GetNextRemindersFromList(remq->active[qindex], tick,
rems));
else {
if ((stat = _GetNextRemindersFromList(remq->oldhead[qindex],
tick, rems)) == CSA_SUCCESS && rem == *rems)
return (_GetNextRemindersFromList(remq->active[qindex],
tick, rems));
else
return (stat);
}
}
static cms_reminder_ref *
_GetReminderRefFromInfo(_DtCmsRemInfo *rem, time_t starttime, time_t runtime)
{
cms_reminder_ref *rptr;
cms_entry *entry = rem->data.e;
int size;
if ((rptr = (cms_reminder_ref *)calloc(1, sizeof(cms_reminder_ref)))
== NULL)
return (NULL);
if ((rptr->reminder_name = strdup(entry->attrs[rem->rem.i].name.name))
== NULL) {
free(rptr);
return (NULL);
}
size = entry->attrs[CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I].value->item.\
opaque_data_value->size;
if ((rptr->entryid = malloc(size)) == NULL) {
free(rptr->reminder_name);
free(rptr);
return (NULL);
} else
strncpy(rptr->entryid, (char *)entry->attrs\
[CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I].value->item.\
opaque_data_value->data, size);
rptr->key.id = entry->key.id;
rptr->key.time = starttime ? starttime : rem->starttime;
rptr->runtime = runtime ? runtime : rem->runtime;
return (rptr);
}
static void
_RemoveReminderFromQ(
_DtCmsRemQueue *remq,
int qindex,
cms_entry *entry,
List_node *lnode, /* zero for one time entries */
time_t starttime,
boolean_t delfwd)
{
_DtCmsRemInfo *rptr, *rptr1 = NULL, *rptr2 = NULL;
time_t lead;
time_t tick;
boolean_t do_old, do_new;
RepeatEventState *restate;
_csa_iso8601_to_duration(entry->attrs[remq->aindex[qindex]].value->\
item.reminder_value->lead_time, &lead);
if (lnode == 0) {
if (entry->key.time - lead < remq->cutoff)
_RemoveReminderFromList(&remq->oldhead[qindex], entry,
starttime, delfwd);
else
_RemoveReminderFromList(&remq->active[qindex], entry,
starttime, delfwd);
} else {
tick = ClosestTick(entry->key.time, entry->key.time, lnode->re,
&restate);
free(restate);
if (do_old = (tick - lead < remq->cutoff))
rptr1 = _RemoveReminderFromList(&remq->oldhead[qindex],
entry, starttime, delfwd);
if (do_new = (lnode->lasttick - lead >= remq->cutoff))
rptr2 = _RemoveReminderFromList(&remq->active[qindex],
entry, starttime, delfwd);
if (rptr = rptr1 ? rptr1 : rptr2) {
if (do_old && do_new) {
/* need to clean up the other queue
* since add reminder will add to both
* queue
*/
if (rptr1 == NULL)
_RemoveReminderFromList(
&remq->oldhead[qindex], entry,
0, B_FALSE);
else
_RemoveReminderFromList(
&remq->active[qindex], entry,
0, B_FALSE);
}
_DtCmsAddReminder4EntryToQ(remq, entry,
remq->aindex[qindex], rptr->lnode);
if (rptr1) free(rptr1);
if (rptr2) free(rptr2);
}
}
}
static _DtCmsRemInfo *
_RemoveReminderFromList(
_DtCmsRemInfo **qhead,
cms_entry *entry,
time_t starttime,
boolean_t delfwd)
{
_DtCmsRemInfo *rptr, *prev;
/* find reminder in list */
for (rptr = *qhead, prev = NULL; rptr != NULL;
prev = rptr, rptr = rptr->next) {
if (rptr->data.e != entry ||
(starttime > 0 && !delfwd && rptr->starttime != starttime)||
(starttime > 0 && delfwd && rptr->starttime < starttime))
{
continue;
}
if (prev == NULL)
*qhead = rptr->next;
else
prev->next = rptr->next;
if (starttime == 0 || delfwd) {
free(rptr);
return (NULL);
} else
return (rptr);
}
return (NULL);
}
/*
* move all reminders in active queue whose runtime < cutoff
* to old queue
*/
static void
_UpdateReminderQ(_DtCmsRemQueue *remq, int qindex)
{
_DtCmsRemInfo *rptr, *nptr;
cms_entry *entry;
time_t lead, tick;
RepeatEventState *restate = NULL;
for (; (rptr = remq->active[qindex]) != NULL &&
rptr->runtime < remq->cutoff; ) {
remq->active[qindex] = rptr->next;
rptr->next = NULL;
if (rptr->lnode == NULL)
_InsertReminder(&remq->oldhead[qindex], rptr);
else {
lead = rptr->starttime - rptr->runtime;
entry = rptr->data.e;
tick = ClosestTick(entry->key.time, entry->key.time,
rptr->lnode->re, &restate);
free(restate);
if (tick == rptr->starttime) {
/* add this to old queue */
_InsertReminder(&remq->oldhead[qindex], rptr);
/* make copy of rptr */
nptr = (_DtCmsRemInfo *)calloc(1,
sizeof(_DtCmsRemInfo));
*nptr = *rptr;
rptr = nptr;
}
if ((rptr->lasttick - lead < remq->cutoff) ||
(tick = _GetNextActiveTick(entry,
remq->cutoff + lead, rptr->lasttick,
rptr->lnode->re)) <= 0)
{
free(rptr);
} else {
rptr->starttime = tick;
rptr->runtime = tick - lead;
_InsertReminder(&remq->active[qindex], rptr);
}
}
}
}
static long
_GetNextActiveTick(
cms_entry *entry,
time_t target,
time_t lasttick,
RepeatEvent *re)
{
RepeatEventState *restate = NULL;
time_t tick;
for (tick = ClosestTick(target, entry->key.time, re, &restate);
tick <= lasttick;
tick = NextTick(tick, entry->key.time, re, restate))
{
if (tick <= 0 || !_DtCmsInExceptionList(entry, tick))
break;
}
free(restate);
return (tick);
}
/*
* The reminders found will be linked with the list
* contained in rf_f
*/
static CSA_return_code
_GetNextRemindersFromList(
_DtCmsRemInfo *rlist,
time_t giventime,
cms_reminder_ref **rf_r)
{
cms_reminder_ref *rptr, *head = NULL, *tail;
time_t tick;
int lead;
/* get from active queue */
for (; rlist != NULL; rlist = rlist->next) {
if (giventime < rlist->runtime)
break;
else if (rlist->lnode) {
/* check the next active tick */
lead = rlist->starttime - rlist->runtime;
tick = _GetNextActiveTick(rlist->data.e,
giventime + lead + 1, rlist->lasttick,
rlist->lnode->re);
if (tick > 0 &&
(head == NULL || (tick-lead <= head->runtime)))
{
if ((rptr = _GetReminderRefFromInfo(rlist, tick,
tick-lead)) == NULL) {
if (head)
_DtCmsFreeReminderRef(head);
return (CSA_E_INSUFFICIENT_MEMORY);
}
if (head == NULL)
head = rptr;
else if (head->runtime = rptr->runtime) {
rptr->next = head;
head = rptr;
} else {
_DtCmsFreeReminderRef(head);
head = rptr;
}
}
}
}
if (rlist) {
if (head) {
if (head->runtime > rlist->runtime) {
_DtCmsFreeReminderRef(head);
head = NULL;
} else if (head->runtime < rlist->runtime)
goto _done;
}
/* now do lookup in the remaining list */
while (rlist != NULL) {
if (rptr = _GetReminderRefFromInfo(rlist, 0, 0)) {
rptr->next = head;
head = rptr;
} else {
if (head) _DtCmsFreeReminderRef(head);
return (CSA_E_INSUFFICIENT_MEMORY);
}
if (rlist->next &&
rlist->next->runtime == rlist->runtime)
rlist = rlist->next;
else
break;
}
}
_done:
/* find tail */
if (head) {
for (tail = head; tail->next != NULL; tail = tail->next) ;
tail->next = *rf_r;
*rf_r = head;
}
return (CSA_SUCCESS);
}
static void
_DtCmsAddReminder4EntryToQ(
_DtCmsRemQueue *remq,
cms_entry *entry,
int aindex,
List_node *lnode)
{
_DtCmsRemInfo *rptr, *rptr2;
int i;
if ((rptr = _BuildReminder4Entry(entry, aindex, lnode, remq->cutoff,
&rptr2)) == NULL)
return;
for (i = 0; i < remq->num_queues; i++) {
if (remq->aindex[i] == aindex) {
if (rptr->runtime >= remq->cutoff)
_InsertReminder(&remq->active[i], rptr);
else
_InsertReminder(&remq->oldhead[i], rptr);
if (rptr2)
_InsertReminder(&remq->active[i], rptr2);
break;
}
}
if (i == remq->num_queues) {
/* expand the queue */
}
}