1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
/*
* iSNS object callbacks for SCN and other stuff
*
* Copyright (C) 2007 Olaf Kirch <olaf.kirch@oracle.com>
*/
#include <stdlib.h>
#include <string.h>
#include <libisns/isns.h>
#include "objects.h"
#include "vendor.h"
#include <libisns/attrs.h>
#include <libisns/util.h>
typedef struct isns_object_notifier isns_object_notifier_t;
struct isns_object_notifier {
isns_list_t list;
isns_db_callback_t * func;
void * data;
};
typedef struct isns_cb_event isns_cb_event_t;
struct isns_cb_event {
isns_list_t list;
isns_db_event_t info;
};
static ISNS_LIST_DECLARE(notifiers);
static ISNS_LIST_DECLARE(events);
static inline void
__isns_db_event(isns_object_t *dst,
isns_object_t *obj,
unsigned int bits,
isns_object_t *trigger)
{
isns_cb_event_t *ev;
ev = isns_calloc(1, sizeof(*ev));
ev->info.ie_recipient = isns_object_get(dst);
ev->info.ie_object = isns_object_get(obj);
ev->info.ie_bits = bits;
ev->info.ie_trigger = isns_object_get(trigger);
isns_list_append(&events, &ev->list);
}
void
isns_object_event(isns_object_t *obj,
unsigned int bits,
isns_object_t *trigger)
{
__isns_db_event(NULL, obj, bits, trigger);
}
void
isns_unicast_event(isns_object_t *dst,
isns_object_t *obj,
unsigned int bits,
isns_object_t *trigger)
{
__isns_db_event(dst, obj, bits, trigger);
}
/*
* Given an object pair and an event bitmask,
* invoke all callbacks
*/
static inline void
isns_call_callbacks(isns_db_event_t *ev)
{
isns_object_t *obj = ev->ie_object;
isns_list_t *pos, *next;
ev->ie_bits |= obj->ie_scn_bits;
if (ev->ie_bits == 0)
return;
isns_list_foreach(¬ifiers, pos, next) {
isns_object_notifier_t *not;
not = isns_list_item(isns_object_notifier_t, list, pos);
not->func(ev, not->data);
}
obj->ie_scn_bits = 0;
}
void
isns_flush_events(void)
{
while (!isns_list_empty(&events)) {
isns_cb_event_t *ev = isns_list_item(isns_cb_event_t, list, events.next);
isns_call_callbacks(&ev->info);
isns_object_release(ev->info.ie_recipient);
isns_object_release(ev->info.ie_object);
isns_object_release(ev->info.ie_trigger);
isns_list_del(&ev->list);
isns_free(ev);
}
}
void
isns_register_callback(isns_db_callback_t *func,
void *user_data)
{
isns_object_notifier_t *not;
not = isns_calloc(1, sizeof(*not));
not->func = func;
not->data = user_data;
isns_list_append(¬ifiers, ¬->list);
}
const char *
isns_event_string(unsigned int bits)
{
static const char *names[16] = {
[ISNS_SCN_DD_MEMBER_ADDED] = "member added",
[ISNS_SCN_DD_MEMBER_REMOVED] = "member removed",
[ISNS_SCN_OBJECT_UPDATED] = "updated",
[ISNS_SCN_OBJECT_ADDED] = "added",
[ISNS_SCN_OBJECT_REMOVED] = "removed",
[ISNS_SCN_MANAGEMENT_REGISTRATION]= "mgmt registration",
[ISNS_SCN_TARGET_AND_SELF_ONLY] = "target+self",
[ISNS_SCN_INITIATOR_AND_SELF_ONLY]= "initiator+self",
};
static char buffer[128];
unsigned int pos = 0, i;
for (i = 0; i < 16; ++i, bits >>= 1) {
if (!(bits & 1))
continue;
if (names[i]) {
snprintf(buffer + pos, sizeof(buffer) - pos,
"%s%s", pos? ", " : "", names[i]);
} else {
snprintf(buffer + pos, sizeof(buffer) - pos,
"%sevent %u", pos? ", " : "", i);
}
pos = strlen(buffer);
}
if (pos == 0)
return "<no event>";
return buffer;
}
|