4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
31 #include <sys/types.h>
36 #include "isns_server.h"
37 #include "isns_cache.h"
40 #include "isns_func.h"
42 #include "isns_msgq.h"
44 #include "isns_sched.h"
55 static ev_t
*ev_list
= NULL
;
57 static uint32_t stopwatch
= 0;
58 static pthread_mutex_t stw_mtx
= PTHREAD_MUTEX_INITIALIZER
;
60 static int wakeup
= 0;
61 static pthread_mutex_t idl_mtx
= PTHREAD_MUTEX_INITIALIZER
;
62 static pthread_cond_t idl_cond
= PTHREAD_COND_INITIALIZER
;
67 extern const int UID_ATTR_INDEX
[MAX_OBJ_TYPE_FOR_SIZE
];
69 extern boolean_t time_to_exit
;
71 extern msg_queue_t
*sys_q
;
73 extern uint64_t esi_threshold
;
76 extern void dump_pdu1(isns_pdu_t
*);
82 static void *esi_monitor(void *);
85 * ****************************************************************************
88 * Make a new portal for ESI event.
90 * uid - the portal object UID.
91 * ip6 - the portal IPv6 format IP address.
92 * port - the portal port.
93 * esip - the ESI port.
94 * return - the new ESI portal.
96 * ****************************************************************************
108 p
= (esi_portal_t
*)malloc(sizeof (esi_portal_t
));
110 if (((int *)ip6
)[0] == 0x00 &&
111 ((int *)ip6
)[1] == 0x00 &&
112 ((uchar_t
*)ip6
)[8] == 0x00 &&
113 ((uchar_t
*)ip6
)[9] == 0x00 &&
114 ((uchar_t
*)ip6
)[10] == 0xFF &&
115 ((uchar_t
*)ip6
)[11] == 0xFF) {
116 p
->sz
= sizeof (in_addr_t
);
117 p
->ip4
= ((uint32_t *)ip6
)[3];
119 p
->sz
= sizeof (in6_addr_t
);
133 * ****************************************************************************
136 * Free a list of portal of one ESI event.
138 * p - the ESI portal.
140 * ****************************************************************************
158 * ****************************************************************************
161 * Make a new ESI event.
163 * uid - the Entity object UID.
164 * eid - the Entity object name.
165 * len - the length of the name.
166 * return - the ESI event.
168 * ****************************************************************************
179 ev
= (ev_t
*)malloc(sizeof (ev_t
));
181 if (pthread_mutex_init(&ev
->mtx
, NULL
) != 0 ||
182 (ev
->eid
= (uchar_t
*)malloc(len
)) == NULL
) {
187 (void) strcpy((char *)ev
->eid
, (char *)eid
);
189 /* initialization time */
190 ev
->flags
= EV_FLAG_INIT
;
197 * ****************************************************************************
200 * Callback function which makes a copy of the portal child object
201 * UIDs from a Network Entity object.
203 * p1 - the Network Entity object.
204 * p2 - the lookup control data.
205 * return - the number of portal object UIDs.
207 * ****************************************************************************
215 isns_obj_t
*obj
= (isns_obj_t
*)p1
;
216 lookup_ctrl_t
*lcp
= (lookup_ctrl_t
*)p2
;
225 cuidp
= get_child_t(obj
, OBJ_PORTAL
);
227 p
= (uint32_t *)malloc(*cuidp
* sizeof (*p
));
230 (void) memcpy(p
, cuidp
, num
* sizeof (*p
));
231 lcp
->data
[1].ptr
= (uchar_t
*)p
;
235 attr
= &obj
->attrs
[ATTR_INDEX_ENTITY(ISNS_ENTITY_REG_PERIOD_ATTR_ID
)];
236 if (attr
->tag
!= 0 && attr
->value
.ui
!= 0) {
237 lcp
->data
[2].ui
= attr
->value
.ui
;
239 /* just one second before the end of the world */
240 lcp
->data
[2].ui
= INFINITY
- 1;
247 * ****************************************************************************
250 * Callback function which gets ESI port number and ESI interval
251 * from a portal object.
253 * p1 - the Portal object.
254 * p2 - the lookup control data.
255 * return - the ESI interval.
257 * ****************************************************************************
275 if (cb_clone_attrs(p1
, p2
) == 0) {
276 obj
= (isns_obj_t
*)p1
;
277 lcp
= (lookup_ctrl_t
*)p2
;
278 ip
= lcp
->data
[1].ip
;
279 esip
= lcp
->data
[2].ui
;
281 attr
= &obj
->attrs
[ATTR_INDEX_PORTAL(
282 ISNS_PORTAL_PORT_ATTR_ID
)];
283 lcp
->data
[0].ui
= attr
->value
.ui
;
284 attr
= &obj
->attrs
[ATTR_INDEX_PORTAL(
285 ISNS_ESI_INTERVAL_ATTR_ID
)];
286 if (attr
->tag
!= 0 && attr
->value
.ui
!= 0) {
287 intval
= attr
->value
.ui
;
289 intval
= DEFAULT_ESI_INTVAL
;
296 return ((int)intval
);
300 * ****************************************************************************
302 * extract_esi_portal:
303 * Extract a list of portal which have an ESI port for an Entity.
305 * uid - the Entity object UID.
306 * intval - the ESI interval for returnning.
307 * return - the list of portals.
309 * ****************************************************************************
311 static esi_portal_t
*
317 esi_portal_t
*list
= NULL
;
322 uint32_t num_of_portal
;
323 uint32_t *portal_uids
;
327 /* prepare for looking up entity object */
328 SET_UID_LCP(&lc
, OBJ_ENTITY
, uid
);
329 lc
.data
[1].ptr
= NULL
;
330 lc
.data
[2].ui
= INFINITY
- 1;
332 /* get the array of the portal uid(s) */
333 num_of_portal
= (uint32_t)cache_lookup(&lc
, NULL
, cb_portal_uids
);
334 portal_uids
= (uint32_t *)lc
.data
[1].ptr
;
335 *intval
= lc
.data
[2].ui
;
337 /* prepare for looking up portal object(s) */
338 SET_UID_LCP(&lc
, OBJ_PORTAL
, 0);
339 lc
.id
[1] = ISNS_PORTAL_IP_ADDR_ATTR_ID
;
340 lc
.id
[2] = ISNS_ESI_PORT_ATTR_ID
;
341 FOR_EACH_OBJS(portal_uids
, num_of_portal
, uid
, {
344 intv
= cache_lookup(&lc
, NULL
, cb_esi_portal
);
346 p
= new_esi_portal(uid
,
347 (in6_addr_t
*)lc
.data
[1].ip
,
348 lc
.data
[0].ui
, lc
.data
[2].ui
);
352 if (*intval
> intv
) {
360 /* free up the portal uid array */
367 * ****************************************************************************
372 * ev - the ESI event.
373 * init - 0: initialization time, otherwise not.
374 * return - error code.
376 * ****************************************************************************
390 /* get the portal(s) which are registered for ESI monitoring */
391 /* and the second interval for ESI or registration expiration */
392 p
= extract_esi_portal(ev
->uid
, &intval
);
397 /* avoid running everything at the same time */
399 /* generate random number within range (0, 1] */
400 rnd
= (rand() + 1) / (double)(RAND_MAX
+ 1);
401 t
= (uint32_t)(intval
* rnd
);
404 /* no portal is registered for ESI monitoring, make */
405 /* an entry for entity registration expiration */
406 ev
->type
= EV_REG_EXP
;
413 /* schedule the event */
414 return (el_add(ev
, t
, NULL
));
422 * ****************************************************************************
425 * The signal handler for SIGALRM, the ESI proc uses the SIGALRM
426 * for waking up to perform the client status inquery.
430 * ****************************************************************************
438 /* wake up the idle */
439 (void) pthread_mutex_lock(&idl_mtx
);
440 wakeup
= 1; /* wake up naturally */
441 (void) pthread_cond_signal(&idl_cond
);
442 (void) pthread_mutex_unlock(&idl_mtx
);
446 * ****************************************************************************
449 * Load an ESI event from data store.
451 * uid - the Entity object UID.
452 * eid - the Entity object name.
453 * len - the length of the name.
454 * return - error code.
456 * ****************************************************************************
467 /* make a new event */
468 ev_t
*ev
= ev_new(uid
, eid
, len
);
470 /* put the new event to the list */
475 ec
= ISNS_RSP_INTERNAL_ERROR
;
482 * ****************************************************************************
485 * Verify ESI port and add the ESI entries after the ESI are loaded.
487 * return - error code.
489 * ****************************************************************************
499 /* add each event from the list */
500 while (ev_list
!= NULL
&& ec
== 0) {
511 * ****************************************************************************
514 * Add a new ESI event when a new Entity is registered.
516 * uid - the Entity object UID.
517 * eid - the Entity object name.
518 * len - the length of the name.
519 * return - error code.
521 * ****************************************************************************
532 /* make a new event */
533 ev_t
*ev
= ev_new(uid
, eid
, len
);
537 ev
->flags
|= EV_FLAG_WAKEUP
;
540 ec
= ISNS_RSP_INTERNAL_ERROR
;
547 * ****************************************************************************
550 * Remove an ESI event immediately.
552 * uid - the Entity object UID.
553 * return - always successful.
555 * ****************************************************************************
562 (void) el_remove(uid
, 0, 0);
568 * ****************************************************************************
571 * Update an ESI event when a Entity object or a Portal object is
572 * removed from server. If the object is being removed because of
573 * ESI failure, the ESI event will be removed with a pending time,
574 * otherwise, the ESI will be removed immediately.
576 * obj - the object being removed.
577 * pending - the pending flag.
578 * return - always successful.
580 * ****************************************************************************
584 const isns_obj_t
*obj
,
592 puid
= get_parent_uid(obj
);
593 uid
= get_obj_uid(obj
);
596 puid
= get_obj_uid(obj
);
605 (void) el_remove(puid
, uid
, pending
);
612 * ****************************************************************************
615 * Get the stopwatch. It might need to signal the condition to
616 * wake up the idle so the stopwatch gets updated.
618 * flag - wake up flag.
619 * return - the stopwatch.
621 * ****************************************************************************
630 /* not re-schedule, wake up idle */
631 (void) pthread_mutex_lock(&idl_mtx
);
633 wakeup
= 2; /* wake up manually */
634 (void) pthread_cond_signal(&idl_cond
);
636 wakeup
= 0; /* clear previous interruption */
638 (void) pthread_mutex_unlock(&idl_mtx
);
640 /* get most current time */
641 (void) pthread_mutex_lock(&stw_mtx
);
643 (void) pthread_mutex_unlock(&stw_mtx
);
649 * ****************************************************************************
652 * Get the time interval of an ESI event.
655 * return - the time interval.
657 * ****************************************************************************
664 return (((ev_t
*)p
)->intval
);
668 * ****************************************************************************
671 * Check the ESI event maching an Entity object.
674 * uid - the Entity object UID.
675 * return - 1: match, otherwise not.
677 * ****************************************************************************
685 if (((ev_t
*)p
)->uid
== uid
) {
693 * ****************************************************************************
696 * Remove a portal or an ESI event. If all of ESI portal has been
697 * removed, the ESI event will be marked as removal pending, which
698 * will result in removing the Entity object after the pending time.
701 * portal_uid - the Portal object UID.
702 * flag - 0: the ESI is currently in use, otherwise it is scheduled.
703 * pending - flag for the ESI removal pending.
704 * return - 0: the ESI is physically removed, otherwise not.
706 * ****************************************************************************
716 ev_t
*ev
= (ev_t
*)p
;
717 esi_portal_t
**pp
, *portal
;
722 /* remove one portal only */
723 if (portal_uid
!= 0) {
726 while (portal
!= NULL
) {
727 /* found the match portal */
728 if (portal
->ref
== portal_uid
) {
729 /* mark it as removed */
732 /* not in use, remove it physically */
735 free_esi_portal(portal
);
740 /* one or more esi portals are available */
741 if (portal
->ref
!= 0) {
750 /* no portal available */
751 if (has_portal
== 0) {
752 state
= (pending
<< 1) | flag
;
755 /* mark the event as removed */
756 ev
->flags
|= EV_FLAG_REMOVE
;
757 isnslog(LOG_DEBUG
, "ev_remove",
758 "%s [%d] is marked as removed.",
759 ev
->type
== EV_ESI
? "ESI" : "REG_EXP",
763 /* physically remove the event */
768 /* mark the event as removal pending */
769 isnslog(LOG_DEBUG
, "ev_remove",
770 "%s [%d] is marked as removal pending.",
771 ev
->type
== EV_ESI
? "ESI" : "REG_EXP",
773 ev
->flags
|= EV_FLAG_REM_P1
;
780 isnslog(LOG_DEBUG
, "ev_remove", "%s [%d] removed portal %d.",
781 ev
->type
== EV_ESI
? "ESI" : "REG_EXP",
782 ev
->uid
, portal_uid
);
789 * ****************************************************************************
796 * ****************************************************************************
803 ev_t
*ev
= (ev_t
*)p
;
805 /* free up all of portals */
806 free_esi_portal(ev
->portal
);
808 isnslog(LOG_DEBUG
, "ev_free",
809 "%s [%d] is physically removed.",
810 ev
->type
== EV_ESI
? "ESI" : "REG_EXP",
820 * ****************************************************************************
823 * Check the initial flag of an ESI event.
826 * return - 0: not initial, otherwise yes.
828 * ****************************************************************************
835 return (((ev_t
*)p
)->flags
& EV_FLAG_INIT
);
839 * ****************************************************************************
842 * Check the again flag of an ESI event.
843 * (this flag might be eliminated and use the init flag.)
846 * return - 0: not again, otherwise yes.
848 * ****************************************************************************
855 return (((ev_t
*)p
)->flags
& EV_FLAG_AGAIN
);
859 * ****************************************************************************
862 * Check the wakeup flag of an ESI event. The idle might need to
863 * wake up before the event is scheduled.
866 * return - 0: no wakeup, otherwise yes.
868 * ****************************************************************************
875 return (((ev_t
*)p
)->flags
& EV_FLAG_WAKEUP
);
879 * ****************************************************************************
882 * Check the removal flag of an ESI event. The ESI entry might be
886 * return - 0: not removed, otherwise yes.
888 * ****************************************************************************
895 return (((ev_t
*)p
)->flags
& EV_FLAG_REMOVE
);
899 * ****************************************************************************
902 * Check the removal pending flag of an ESI event. The ESI entry
903 * might be marked as removal pending. If it is, we will switch the
904 * event type and change the time interval.
907 * return - 0: not removal pending, otherwise yes.
909 * ****************************************************************************
916 ev_t
*ev
= (ev_t
*)p
;
917 if ((ev
->flags
& EV_FLAG_REM_P
) != 0) {
918 if (ev
->type
!= EV_REG_EXP
) {
919 isnslog(LOG_DEBUG
, "ev_rem_pending",
920 "%s [%d] is changed to REG_EXP.",
921 ev
->type
== EV_ESI
? "ESI" : "REG_EXP",
923 ev
->type
= EV_REG_EXP
;
924 ev
->intval
*= 2; /* after 2 ESI interval */
933 * ****************************************************************************
936 * Reset the event flag.
940 * ****************************************************************************
947 ev_t
*ev
= (ev_t
*)p
;
949 /* not acutally clear it, need to set again flag */
950 /* and keep the removal pending flag */
951 ev
->flags
= EV_FLAG_AGAIN
| (ev
->flags
& EV_FLAG_REM_P
);
955 * ****************************************************************************
958 * Append an ESI event to the list, the list contains all of
959 * ESI events which are being processed at present.
963 * ****************************************************************************
978 * ****************************************************************************
981 * Strip off an ESI event from the list after the event is being
982 * processed, it will be scheduled in the scheduler.
986 * ****************************************************************************
993 ev_t
**evp
= &ev_list
;
1007 * ****************************************************************************
1010 * Remove an ESI event or a portal of an ESI event from the event list.
1012 * id1 - the Entity object UID.
1013 * id2 - the Portal object UID.
1014 * pending - the pending flag.
1015 * return - 1: found a match event, otherwise not.
1017 * ****************************************************************************
1028 while (ev
!= NULL
) {
1030 if (ev_match(ev
, id1
) != 0) {
1031 /* lock the event */
1032 (void) pthread_mutex_lock(&ev
->mtx
);
1033 /* mark it as removed */
1034 (void) ev_remove(ev
, id2
, 0, pending
);
1035 /* unlock the event */
1036 (void) pthread_mutex_unlock(&ev
->mtx
);
1037 /* tell caller removal is done */
1047 #define ALARM_MAX (21427200)
1050 * ****************************************************************************
1053 * Idle for certain amount of time or a wakeup signal is recieved.
1055 * t - the idle time.
1056 * return - the time that idle left.
1058 * ****************************************************************************
1065 uint32_t t1
, t2
, t3
= 0;
1068 /* hold the mutex for stopwatch update */
1069 (void) pthread_mutex_lock(&stw_mtx
);
1072 if (t
> ALARM_MAX
) {
1081 /* hold the mutex for idle condition */
1082 (void) pthread_mutex_lock(&idl_mtx
);
1084 /* wait on condition variable to wake up idle */
1085 while (wakeup
== 0) {
1086 (void) pthread_cond_wait(&idl_cond
, &idl_mtx
);
1091 /* clean wakeup flag */
1094 /* release the mutex for idle condition */
1095 (void) pthread_mutex_unlock(&idl_mtx
);
1100 /* seconds actually slept */
1103 } while (t
> 0 && idl_int
== 0);
1105 /* increate the stopwatch by the actually slept time */
1108 /* release the mutex after stopwatch is updated */
1109 (void) pthread_mutex_unlock(&stw_mtx
);
1111 /* return the amount of time which is not slept */
1116 * ****************************************************************************
1119 * Execute an event. To inquiry the client status or
1120 * perform registration expiration.
1124 * ****************************************************************************
1135 if (pthread_create(&tid
, NULL
,
1136 esi_monitor
, (void *)ev
) != 0) {
1137 isnslog(LOG_DEBUG
, "ev_ex", "pthread_create() failed.");
1138 /* reschedule for next occurence */
1139 (void) el_add(ev
, 0, NULL
);
1141 /* increase the thread ref count */
1146 (void) queue_msg_set(sys_q
, REG_EXP
, (void *)ev
);
1154 * ****************************************************************************
1157 * ESI thread entry, which:
1158 * 1: fetch an event from schedule,
1159 * 2: idle for some time,
1160 * 3: execute the event or re-schedule it,
1161 * 4: repeat from step 1 before server is being shutdown.
1163 * arg - the thread argument.
1165 * ****************************************************************************
1178 while (time_to_exit
== B_FALSE
) {
1179 ev
= (ev_t
*)el_first(&pt
);
1181 /* caculate the idle time */
1183 if (pt
> stopwatch
) {
1193 /* block for a certain amount of time */
1195 isnslog(LOG_DEBUG
, "esi_proc",
1196 "idle for %d seconds.", t
);
1202 isnslog(LOG_DEBUG
, "esi_proc",
1203 "idle interrupted after idle for "
1204 "%d seconds.", t
- t1
);
1206 if (time_to_exit
!= B_FALSE
) {
1207 ev
= NULL
; /* force break */
1208 } else if (ev
!= NULL
) {
1210 /* not naturally waken up */
1211 /* reschedule current event */
1213 (void) el_add(ev
, pt
, &evp
);
1218 isnslog(LOG_DEBUG
, "esi_proc",
1219 "excute the cron job[%d].",
1225 } while (ev
!= NULL
);
1232 * ****************************************************************************
1235 * Ping the client with the ESI retry threshold for status inquiry.
1237 * so - the socket descriptor.
1238 * pdu - the ESI packet.
1239 * pl - the length of packet.
1240 * return - 1: status inquired, otherwise not.
1242 * ****************************************************************************
1252 isns_pdu_t
*rsp
= NULL
;
1258 if (isns_send_pdu(so
, pdu
, pl
) == 0) {
1259 if (isns_rcv_pdu(so
, &rsp
, &rsp_sz
,
1260 ISNS_RCV_SHORT_TIMEOUT
) > 0) {
1268 /* retry after 1 second */
1272 } while (try_cnt
< esi_threshold
);
1282 * ****************************************************************************
1285 * Child thread for client status mornitoring.
1287 * arg - the ESI event.
1289 * ****************************************************************************
1296 ev_t
*ev
= (ev_t
*)arg
;
1301 isns_pdu_t
*pdu
= NULL
;
1310 /* lock the event for esi monitoring */
1311 (void) pthread_mutex_lock(&ev
->mtx
);
1313 if (evf_rem(ev
) != 0) {
1315 } else if (evf_rem_pending(ev
) != 0) {
1322 /* allocate ESI PDU */
1323 if (pdu_reset_esi(&pdu
, &pl
, &sz
) != 0 ||
1324 pdu_add_tlv(&pdu
, &pl
, &sz
,
1325 ISNS_TIMESTAMP_ATTR_ID
, 8, (void *)&t
, 1) != 0 ||
1326 pdu_add_tlv(&pdu
, &pl
, &sz
,
1327 ISNS_EID_ATTR_ID
, ev
->eid_len
, (void *)ev
->eid
, 0) != 0) {
1328 /* no memory, will retry later */
1333 pdu
->version
= htons((uint16_t)ISNSP_VERSION
);
1334 pdu
->func_id
= htons((uint16_t)ISNS_ESI
);
1335 pdu
->xid
= htons(get_server_xid());
1337 /* keep the current lenght of the playload */
1343 /* skip IPv6 portal */
1344 p
->sz
!= sizeof (in6_addr_t
) &&
1345 pdu_add_tlv(&pdu
, &pl
, &sz
,
1346 ISNS_PORTAL_IP_ADDR_ATTR_ID
,
1347 sizeof (in6_addr_t
), (void *)p
->ip6
, 0) == 0 &&
1348 pdu_add_tlv(&pdu
, &pl
, &sz
,
1349 ISNS_PORTAL_PORT_ATTR_ID
,
1350 4, (void *)p
->port
, 0) == 0) {
1352 so
= connect_to(p
->sz
, p
->ip4
, p
->ip6
, p
->esip
);
1354 feedback
= esi_ping(so
, pdu
, pl
);
1358 /* cannot connect, portal is dead */
1361 if (feedback
== 0) {
1362 isnslog(LOG_DEBUG
, "esi_monitor",
1363 "ESI ping failed.");
1364 (void) queue_msg_set(sys_q
, DEAD_PORTAL
,
1375 /* unlock the event after esi monitoring is done */
1376 (void) pthread_mutex_unlock(&ev
->mtx
);
1383 /* set reschedule flags */
1384 ev
->flags
|= EV_FLAG_WAKEUP
;
1386 /* reschedule for next occurence */
1387 (void) el_add(ev
, 0, NULL
);
1389 /* decrease the thread ref count */
1396 * ****************************************************************************
1399 * Handles the dead portal that ESI detected.
1401 * uid - the Portal object UID.
1403 * ****************************************************************************
1414 /* prepare the lookup control for deregistration */
1415 SET_UID_LCP(&lc
, OBJ_PORTAL
, uid
);
1417 /* lock the cache for object deregistration */
1418 (void) cache_lock_write();
1420 /* deregister the portal */
1421 ec
= dereg_object(&lc
, 1);
1423 /* unlock cache and sync with data store */
1424 (void) cache_unlock_sync(ec
);
1428 * ****************************************************************************
1431 * Handles the Entity registration expiration.
1433 * p - the ESI event.
1435 * ****************************************************************************
1443 ev_t
*ev
= (ev_t
*)p
;
1446 /* prepare the lookup control for deregistration */
1447 SET_UID_LCP(&lc
, OBJ_ENTITY
, ev
->uid
);
1449 /* lock the cache for object deregistration */
1450 (void) cache_lock_write();
1452 if (evf_rem(ev
) == 0) {
1453 /* deregister the entity */
1454 ec
= dereg_object(&lc
, 0);
1456 /* unlock cache and sync with data store */
1457 ec
= cache_unlock_sync(ec
);
1460 /* successfuk, mark ev as removed */
1461 ev
->flags
|= EV_FLAG_REMOVE
;
1463 /* failed, retry after 3 mintues */
1464 ev
->intval
= 3 * 60;
1465 isnslog(LOG_DEBUG
, "reg_expiring",
1466 "dereg failed, retry after 3 mintues.");
1469 /* ev is marked as removed, no need to dereg */
1470 (void) cache_unlock_nosync();
1473 /* reschedule it for next occurence */
1474 (void) el_add(ev
, 0, NULL
);