1 /*
2 * Copyright (c) 2012-2016 Cisco Systems, Inc. All rights reserved.
3 * Copyright (c) 2012 Los Alamos National Security, LLC. All rights reserved
4 * Copyright (c) 2015 Intel, Inc. All rights reserved
5 * $COPYRIGHT$
6 *
7 * Additional copyrights may follow
8 *
9 * $HEADER$
10 */
11
12 #include "opal_config.h"
13
14 #include <stdio.h>
15 #include <stddef.h>
16
17 #include "opal/mca/event/event.h"
18 #include "opal/class/opal_hotel.h"
19
20
local_eviction_callback(int fd,short flags,void * arg)21 static void local_eviction_callback(int fd, short flags, void *arg)
22 {
23 opal_hotel_room_eviction_callback_arg_t *eargs =
24 (opal_hotel_room_eviction_callback_arg_t*) arg;
25 void *occupant = eargs->hotel->rooms[eargs->room_num].occupant;
26
27 /* Remove the occurpant from the room.
28
29 Do not change this logic without also changing the same logic
30 in opal_hotel_checkout() and
31 opal_hotel_checkout_and_return_occupant(). */
32 opal_hotel_t *hotel = eargs->hotel;
33 opal_hotel_room_t *room = &(hotel->rooms[eargs->room_num]);
34 room->occupant = NULL;
35 hotel->last_unoccupied_room++;
36 assert(hotel->last_unoccupied_room < hotel->num_rooms);
37 hotel->unoccupied_rooms[hotel->last_unoccupied_room] = eargs->room_num;
38
39 /* Invoke the user callback to tell them that they were evicted */
40 hotel->evict_callback_fn(hotel,
41 eargs->room_num,
42 occupant);
43 }
44
45
opal_hotel_init(opal_hotel_t * h,int num_rooms,opal_event_base_t * evbase,uint32_t eviction_timeout,int eviction_event_priority,opal_hotel_eviction_callback_fn_t evict_callback_fn)46 int opal_hotel_init(opal_hotel_t *h, int num_rooms,
47 opal_event_base_t *evbase,
48 uint32_t eviction_timeout,
49 int eviction_event_priority,
50 opal_hotel_eviction_callback_fn_t evict_callback_fn)
51 {
52 int i;
53
54 /* Bozo check */
55 if (num_rooms <= 0 ||
56 NULL == evict_callback_fn) {
57 return OPAL_ERR_BAD_PARAM;
58 }
59
60 h->num_rooms = num_rooms;
61 h->evbase = evbase;
62 h->eviction_timeout.tv_usec = eviction_timeout % 1000000;
63 h->eviction_timeout.tv_sec = eviction_timeout / 1000000;
64 h->evict_callback_fn = evict_callback_fn;
65 h->rooms = (opal_hotel_room_t*)malloc(num_rooms * sizeof(opal_hotel_room_t));
66 if (NULL != evict_callback_fn) {
67 h->eviction_args =
68 (opal_hotel_room_eviction_callback_arg_t*)malloc(num_rooms * sizeof(opal_hotel_room_eviction_callback_arg_t));
69 }
70 h->unoccupied_rooms = (int*) malloc(num_rooms * sizeof(int));
71 h->last_unoccupied_room = num_rooms - 1;
72
73 for (i = 0; i < num_rooms; ++i) {
74 /* Mark this room as unoccupied */
75 h->rooms[i].occupant = NULL;
76
77 /* Setup this room in the unoccupied index array */
78 h->unoccupied_rooms[i] = i;
79
80 /* Setup the eviction callback args */
81 h->eviction_args[i].hotel = h;
82 h->eviction_args[i].room_num = i;
83
84 /* Create this room's event (but don't add it) */
85 if (NULL != h->evbase) {
86 opal_event_set(h->evbase,
87 &(h->rooms[i].eviction_timer_event),
88 -1, 0, local_eviction_callback,
89 &(h->eviction_args[i]));
90
91 /* Set the priority so it gets serviced properly */
92 opal_event_set_priority(&(h->rooms[i].eviction_timer_event),
93 eviction_event_priority);
94 }
95 }
96
97 return OPAL_SUCCESS;
98 }
99
constructor(opal_hotel_t * h)100 static void constructor(opal_hotel_t *h)
101 {
102 h->num_rooms = 0;
103 h->evbase = NULL;
104 h->eviction_timeout.tv_sec = 0;
105 h->eviction_timeout.tv_usec = 0;
106 h->evict_callback_fn = NULL;
107 h->rooms = NULL;
108 h->eviction_args = NULL;
109 h->unoccupied_rooms = NULL;
110 h->last_unoccupied_room = -1;
111 }
112
destructor(opal_hotel_t * h)113 static void destructor(opal_hotel_t *h)
114 {
115 int i;
116
117 /* Go through all occupied rooms and destroy their events */
118 if (NULL != h->evbase) {
119 for (i = 0; i < h->num_rooms; ++i) {
120 if (NULL != h->rooms[i].occupant) {
121 opal_event_del(&(h->rooms[i].eviction_timer_event));
122 }
123 }
124 }
125
126 if (NULL != h->rooms) {
127 free(h->rooms);
128 }
129 if (NULL != h->eviction_args) {
130 free(h->eviction_args);
131 }
132 if (NULL != h->unoccupied_rooms) {
133 free(h->unoccupied_rooms);
134 }
135 }
136
137 OBJ_CLASS_INSTANCE(opal_hotel_t,
138 opal_object_t,
139 constructor,
140 destructor);
141