diff --git a/exec/apidef.c b/exec/apidef.c index 479b7970..2d0b6cd7 100644 --- a/exec/apidef.c +++ b/exec/apidef.c @@ -1,189 +1,189 @@ /* * Copyright (c) 2008, 2009 Red Hat, Inc. * * All rights reserved. * * Author: Steven Dake (sdake@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" #include "timer.h" #include "sync.h" #include "quorum.h" #include "schedwrk.h" #include "main.h" #include "apidef.h" #include #include "service.h" LOGSYS_DECLARE_SUBSYS ("APIDEF"); /* * Remove compile warnings about type name changes in corosync_tpg_group */ typedef int (*typedef_tpg_join) ( - hdb_handle_t, + void *, const struct corosync_tpg_group *, size_t); -typedef int (*typedef_tpg_leave) (hdb_handle_t, +typedef int (*typedef_tpg_leave) (void *, const struct corosync_tpg_group *, size_t); typedef int (*typedef_tpg_groups_mcast_groups) ( - hdb_handle_t, int, + void *, int, const struct corosync_tpg_group *, size_t groups_cnt, const struct iovec *, unsigned int); typedef int (*typedef_tpg_groups_send_ok) ( - hdb_handle_t, + void *, const struct corosync_tpg_group *, size_t groups_cnt, struct iovec *, int); static inline void _corosync_public_exit_error (cs_fatal_error_t err, const char *file, unsigned int line) __attribute__((noreturn)); static inline void _corosync_public_exit_error ( cs_fatal_error_t err, const char *file, unsigned int line) { _corosync_exit_error (err, file, line); } static struct corosync_api_v1 apidef_corosync_api_v1 = { .timer_add_duration = corosync_timer_add_duration, .timer_add_absolute = corosync_timer_add_absolute, .timer_delete = corosync_timer_delete, .timer_time_get = cs_timer_time_get, .timer_expire_time_get = corosync_timer_expire_time_get, .ipc_source_set = message_source_set, .ipc_source_is_local = message_source_is_local, .ipc_private_data_get = cs_ipcs_private_data_get, .ipc_response_iov_send = cs_ipcs_response_iov_send, .ipc_response_send = cs_ipcs_response_send, .ipc_dispatch_send = cs_ipcs_dispatch_send, .ipc_dispatch_iov_send = cs_ipcs_dispatch_iov_send, .ipc_refcnt_inc = cs_ipc_refcnt_inc, .ipc_refcnt_dec = cs_ipc_refcnt_dec, .totem_nodeid_get = totempg_my_nodeid_get, .totem_family_get = totempg_my_family_get, .totem_ring_reenable = totempg_ring_reenable, .totem_mcast = main_mcast, .totem_ifaces_get = totempg_ifaces_get, .totem_ifaces_print = totempg_ifaces_print, .totem_ip_print = totemip_print, .totem_crypto_set = totempg_crypto_set, .totem_callback_token_create = totempg_callback_token_create, .totem_get_stats = totempg_get_stats, .tpg_init = totempg_groups_initialize, .tpg_exit = NULL, /* missing from totempg api */ .tpg_join = (typedef_tpg_join)totempg_groups_join, .tpg_leave = (typedef_tpg_leave)totempg_groups_leave, .tpg_joined_mcast = totempg_groups_mcast_joined, .tpg_joined_reserve = totempg_groups_joined_reserve, .tpg_joined_release = totempg_groups_joined_release, .tpg_groups_mcast = (typedef_tpg_groups_mcast_groups)totempg_groups_mcast_groups, .tpg_groups_reserve = NULL, .tpg_groups_release = NULL, .schedwrk_create = schedwrk_create, .schedwrk_create_nolock = schedwrk_create_nolock, .schedwrk_destroy = schedwrk_destroy, .sync_request = NULL, //sync_request, .quorum_is_quorate = corosync_quorum_is_quorate, .quorum_register_callback = corosync_quorum_register_callback, .quorum_unregister_callback = corosync_quorum_unregister_callback, .quorum_initialize = corosync_quorum_initialize, .service_link_and_init = corosync_service_link_and_init, .service_unlink_and_exit = corosync_service_unlink_and_exit, .plugin_interface_reference = lcr_ifact_reference, .plugin_interface_release = lcr_ifact_release, .error_memory_failure = _corosync_out_of_memory_error, .fatal_error = _corosync_public_exit_error, .shutdown_request = corosync_shutdown_request, .state_dump = corosync_state_dump, .poll_handle_get = cs_poll_handle_get, .poll_dispatch_add = cs_poll_dispatch_add, .poll_dispatch_delete = cs_poll_dispatch_delete }; void apidef_init (struct objdb_iface_ver0 *objdb) { apidef_corosync_api_v1.object_create = objdb->object_create; apidef_corosync_api_v1.object_priv_set = objdb->object_priv_set; apidef_corosync_api_v1.object_key_create = objdb->object_key_create; apidef_corosync_api_v1.object_destroy = objdb->object_destroy; apidef_corosync_api_v1.object_valid_set = objdb->object_valid_set; apidef_corosync_api_v1.object_key_valid_set = objdb->object_key_valid_set; apidef_corosync_api_v1.object_find_create = objdb->object_find_create; apidef_corosync_api_v1.object_find_next = objdb->object_find_next; apidef_corosync_api_v1.object_find_destroy = objdb->object_find_destroy; apidef_corosync_api_v1.object_key_get = objdb->object_key_get; apidef_corosync_api_v1.object_priv_get = objdb->object_priv_get; apidef_corosync_api_v1.object_key_replace = objdb->object_key_replace; apidef_corosync_api_v1.object_key_delete = objdb->object_key_delete; apidef_corosync_api_v1.object_iter_reset = objdb->object_iter_reset; apidef_corosync_api_v1.object_iter = objdb->object_iter; apidef_corosync_api_v1.object_key_iter = objdb->object_key_iter; apidef_corosync_api_v1.object_parent_get = objdb->object_parent_get; apidef_corosync_api_v1.object_name_get = objdb->object_name_get; apidef_corosync_api_v1.object_dump = objdb->object_dump; apidef_corosync_api_v1.object_key_iter_from = objdb->object_key_iter_from; apidef_corosync_api_v1.object_track_start = objdb->object_track_start; apidef_corosync_api_v1.object_track_stop = objdb->object_track_stop; apidef_corosync_api_v1.object_write_config = objdb->object_write_config; apidef_corosync_api_v1.object_reload_config = objdb->object_reload_config; apidef_corosync_api_v1.object_key_increment = objdb->object_key_increment; apidef_corosync_api_v1.object_key_decrement = objdb->object_key_decrement; apidef_corosync_api_v1.object_key_create_typed = objdb->object_key_create_typed; apidef_corosync_api_v1.object_key_get_typed = objdb->object_key_get_typed; apidef_corosync_api_v1.object_key_iter_typed = objdb->object_key_iter_typed; } struct corosync_api_v1 *apidef_get (void) { return (&apidef_corosync_api_v1); } diff --git a/exec/vsf_ykd.c b/exec/vsf_ykd.c index ccc26c63..3e3dfa8a 100644 --- a/exec/vsf_ykd.c +++ b/exec/vsf_ykd.c @@ -1,564 +1,564 @@ /* * Copyright (c) 2005 MontaVista Software, Inc. * Copyright (c) 2006-2009 Red Hat, Inc. * * All rights reserved. * * Author: Steven Dake (sdake@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include LOGSYS_DECLARE_SUBSYS ("YKD"); #define YKD_PROCESSOR_COUNT_MAX 32 enum ykd_header_values { YKD_HEADER_SENDSTATE = 0, YKD_HEADER_ATTEMPT = 1 }; enum ykd_mode { YKD_MODE_SENDSTATE = 0, YKD_MODE_ATTEMPT = 1 }; struct ykd_header { int id; }; struct ykd_session { unsigned int member_list[YKD_PROCESSOR_COUNT_MAX]; int member_list_entries; int session_id; }; struct ykd_state { struct ykd_session last_primary; struct ykd_session last_formed[YKD_PROCESSOR_COUNT_MAX]; int last_formed_entries; struct ykd_session ambiguous_sessions[YKD_PROCESSOR_COUNT_MAX]; int ambiguous_sessions_entries; int session_id; }; struct state_received { unsigned int nodeid; int received; struct ykd_state ykd_state; }; struct ykd_state ykd_state; -static hdb_handle_t ykd_group_handle; +static void *ykd_group_handle; static struct state_received state_received_confchg[YKD_PROCESSOR_COUNT_MAX]; static int state_received_confchg_entries; static struct state_received state_received_process[YKD_PROCESSOR_COUNT_MAX]; static int state_received_process_entries; static enum ykd_mode ykd_mode; static unsigned int ykd_view_list[YKD_PROCESSOR_COUNT_MAX]; static int ykd_view_list_entries; static int session_id_max; static struct ykd_session *last_primary_max; static struct ykd_session ambiguous_sessions_max[YKD_PROCESSOR_COUNT_MAX]; static int ambiguous_sessions_max_entries; static int ykd_primary_designated = 0; static struct memb_ring_id ykd_ring_id; hdb_handle_t schedwrk_attempt_send_callback_handle; hdb_handle_t schedwrk_state_send_callback_handle; static struct corosync_api_v1 *api; static void (*ykd_primary_callback_fn) ( const unsigned int *view_list, size_t view_list_entries, int primary_designated, struct memb_ring_id *ring_id) = NULL; static void ykd_state_init (void) { ykd_state.session_id = 0; ykd_state.last_formed_entries = 0; ykd_state.ambiguous_sessions_entries = 0; ykd_state.last_primary.session_id = 0; ykd_state.last_primary.member_list_entries = 0; } static int ykd_state_send_msg (const void *context) { struct iovec iovec[2]; struct ykd_header header; int res; header.id = YKD_HEADER_SENDSTATE; iovec[0].iov_base = (char *)&header; iovec[0].iov_len = sizeof (struct ykd_header); iovec[1].iov_base = (char *)&ykd_state; iovec[1].iov_len = sizeof (struct ykd_state); res = api->tpg_joined_mcast (ykd_group_handle, iovec, 2, TOTEM_AGREED); return (res); } static void ykd_state_send (void) { api->schedwrk_create ( &schedwrk_state_send_callback_handle, ykd_state_send_msg, NULL); } static int ykd_attempt_send_msg (const void *context) { struct iovec iovec; struct ykd_header header; int res; header.id = YKD_HEADER_ATTEMPT; iovec.iov_base = (char *)&header; iovec.iov_len = sizeof (struct ykd_header); res = api->tpg_joined_mcast (ykd_group_handle, &iovec, 1, TOTEM_AGREED); return (res); } static void ykd_attempt_send (void) { api->schedwrk_create ( &schedwrk_attempt_send_callback_handle, ykd_attempt_send_msg, NULL); } static void compute (void) { int i; int j; session_id_max = 0; last_primary_max = &state_received_process[0].ykd_state.last_primary; ambiguous_sessions_max_entries = 0; for (i = 0; i < state_received_process_entries; i++) { /* * Calculate maximum session id */ if (state_received_process[i].ykd_state.session_id > session_id_max) { session_id_max = state_received_process[i].ykd_state.session_id; } /* * Calculate maximum primary id */ if (state_received_process[i].ykd_state.last_primary.session_id > last_primary_max->session_id) { last_primary_max = &state_received_process[i].ykd_state.last_primary; } /* * generate the maximum ambiguous sessions list */ for (j = 0; j < state_received_process[i].ykd_state.ambiguous_sessions_entries; j++) { if (state_received_process[i].ykd_state.ambiguous_sessions[j].session_id > last_primary_max->session_id) { memcpy (&ambiguous_sessions_max[ambiguous_sessions_max_entries], &state_received_process[i].ykd_state.ambiguous_sessions[j], sizeof (struct ykd_session)); ambiguous_sessions_max_entries += 1; } } } } static int subquorum ( unsigned int *member_list, int member_list_entries, struct ykd_session *session) { int intersections = 0; int i; int j; for (i = 0; i < member_list_entries; i++) { for (j = 0; j < session->member_list_entries; j++) { if (member_list[i] == session->member_list[j]) { intersections += 1; } } } /* * even split */ if (intersections == (session->member_list_entries - intersections)) { return (1); } else /* * majority split */ if (intersections > (session->member_list_entries - intersections)) { return (1); } return (0); } static int decide (void) { int i; /* * Determine if there is a subquorum */ if (subquorum (ykd_view_list, ykd_view_list_entries, last_primary_max) == 0) { return (0); } for (i = 0; i < ambiguous_sessions_max_entries; i++) { if (subquorum (ykd_view_list, ykd_view_list_entries, &ambiguous_sessions_max[i]) == 0) { return (0); } } return (1); } static void ykd_session_endian_convert (struct ykd_session *ykd_session) { int i; ykd_session->member_list_entries = swab32 (ykd_session->member_list_entries); ykd_session->session_id = swab32 (ykd_session->session_id); for (i = 0; i < ykd_session->member_list_entries; i++) { ykd_session->member_list[i] = swab32 (ykd_session->member_list[i]); } } static void ykd_state_endian_convert (struct ykd_state *state) { int i; ykd_session_endian_convert (&state->last_primary); state->last_formed_entries = swab32 (state->last_formed_entries); state->ambiguous_sessions_entries = swab32 (state->ambiguous_sessions_entries); state->session_id = swab32 (state->session_id); for (i = 0; i < state->last_formed_entries; i++) { ykd_session_endian_convert (&state->last_formed[i]); } for (i = 0; i < state->ambiguous_sessions_entries; i++) { ykd_session_endian_convert (&state->ambiguous_sessions[i]); } } static void ykd_deliver_fn ( unsigned int nodeid, const void *msg, unsigned int msg_len, int endian_conversion_required) { int all_received = 1; int state_position = 0; int i; struct ykd_header *header = (struct ykd_header *)msg; char *msg_state = (char *)msg + sizeof (struct ykd_header); /* * If this is a localhost address, this node is always primary */ #ifdef TODO if (totemip_localhost_check (source_addr)) { log_printf (LOGSYS_LEVEL_NOTICE, "This processor is within the primary component.\n"); primary_designated = 1; ykd_primary_callback_fn ( ykd_view_list, ykd_view_list_entries, primary_designated, &ykd_ring_id); return; } #endif if (endian_conversion_required && (msg_len > sizeof (struct ykd_header))) { ykd_state_endian_convert ((struct ykd_state *)msg_state); } /* * Set completion for source_addr's address */ for (state_position = 0; state_position < state_received_confchg_entries; state_position++) { if (nodeid == state_received_process[state_position].nodeid) { /* * State position contains the address of the state to modify * This may be used later by the other algorithms */ state_received_process[state_position].received = 1; break; } } /* * Test if all nodes have submitted their state data */ for (i = 0; i < state_received_confchg_entries; i++) { if (state_received_process[i].received == 0) { all_received = 0; } } /* * Ignore messages from a different state */ if ((ykd_mode == YKD_MODE_SENDSTATE && header->id == YKD_HEADER_ATTEMPT) || (ykd_mode == YKD_MODE_ATTEMPT && header->id == YKD_HEADER_SENDSTATE)) return; switch (ykd_mode) { case YKD_MODE_SENDSTATE: assert (msg_len > sizeof (struct ykd_header)); /* * Copy state information for the sending processor */ memcpy (&state_received_process[state_position].ykd_state, msg_state, sizeof (struct ykd_state)); /* * Try to form a component */ if (all_received) { for (i = 0; i < state_received_confchg_entries; i++) { state_received_process[i].received = 0; } ykd_mode = YKD_MODE_ATTEMPT; // TODO resolve optimizes for failure conditions during ykd calculation // resolve(); compute(); if (decide ()) { ykd_state.session_id = session_id_max + 1; memcpy (ykd_state.ambiguous_sessions[ykd_state.ambiguous_sessions_entries].member_list, ykd_view_list, sizeof (unsigned int) * ykd_view_list_entries); ykd_state.ambiguous_sessions[ykd_state.ambiguous_sessions_entries].member_list_entries = ykd_view_list_entries; ykd_state.ambiguous_sessions_entries += 1; ykd_attempt_send(); } } break; case YKD_MODE_ATTEMPT: if (all_received) { log_printf (LOGSYS_LEVEL_NOTICE, "This processor is within the primary component.\n"); ykd_primary_designated = 1; ykd_primary_callback_fn ( ykd_view_list, ykd_view_list_entries, ykd_primary_designated, &ykd_ring_id); memcpy (ykd_state.last_primary.member_list, ykd_view_list, sizeof (ykd_view_list)); ykd_state.last_primary.member_list_entries = ykd_view_list_entries; ykd_state.last_primary.session_id = ykd_state.session_id; ykd_state.ambiguous_sessions_entries = 0; } break; } } int first_run = 1; static void ykd_confchg_fn ( enum totem_configuration_type configuration_type, const unsigned int *member_list, size_t member_list_entries, const unsigned int *left_list, size_t left_list_entries, const unsigned int *joined_list, size_t joined_list_entries, const struct memb_ring_id *ring_id) { int i; if (configuration_type != TOTEM_CONFIGURATION_REGULAR) { return; } memcpy (&ykd_ring_id, ring_id, sizeof (struct memb_ring_id)); if (first_run) { ykd_state.last_primary.member_list[0] = api->totem_nodeid_get(); ykd_state.last_primary.member_list_entries = 1; ykd_state.last_primary.session_id = 0; first_run = 0; } memcpy (ykd_view_list, member_list, member_list_entries * sizeof (unsigned int)); ykd_view_list_entries = member_list_entries; ykd_mode = YKD_MODE_SENDSTATE; ykd_primary_designated = 0; ykd_primary_callback_fn ( ykd_view_list, ykd_view_list_entries, ykd_primary_designated, &ykd_ring_id); memset (&state_received_confchg, 0, sizeof (state_received_confchg)); for (i = 0; i < member_list_entries; i++) { state_received_confchg[i].nodeid = member_list[i]; state_received_confchg[i].received = 0; } memcpy (state_received_process, state_received_confchg, sizeof (state_received_confchg)); state_received_confchg_entries = member_list_entries; state_received_process_entries = member_list_entries; ykd_state_send (); } struct corosync_tpg_group ykd_group = { .group = "ykd", .group_len = 3 }; static void ykd_init ( struct corosync_api_v1 *corosync_api, quorum_set_quorate_fn_t set_primary) { ykd_primary_callback_fn = set_primary; api = corosync_api; api->tpg_init ( &ykd_group_handle, ykd_deliver_fn, ykd_confchg_fn); api->tpg_join ( ykd_group_handle, &ykd_group, 1); ykd_state_init (); } /* * lcrso object definition */ static struct quorum_services_api_ver1 vsf_ykd_iface_ver0 = { .init = ykd_init, }; static struct lcr_iface corosync_vsf_ykd_ver0[1] = { { .name = "corosync_quorum_ykd", .version = 0, .versions_replace = 0, .versions_replace_count = 0, .dependencies = 0, .dependency_count = 0, .constructor = NULL, .destructor = NULL, .interfaces = (void **)(void *)&vsf_ykd_iface_ver0, } }; static struct lcr_comp vsf_ykd_comp_ver0 = { .iface_count = 1, .ifaces = corosync_vsf_ykd_ver0 }; #ifdef COROSYNC_SOLARIS void corosync_lcr_component_register (void); void corosync_lcr_component_register (void) { #else __attribute__ ((constructor)) static void corosync_lcr_component_register (void) { #endif lcr_component_register (&vsf_ykd_comp_ver0); } diff --git a/include/corosync/engine/coroapi.h b/include/corosync/engine/coroapi.h index c1a6de5b..567d14f9 100644 --- a/include/corosync/engine/coroapi.h +++ b/include/corosync/engine/coroapi.h @@ -1,711 +1,711 @@ /* * Copyright (c) 2008, 2009 Red Hat, Inc. * * All rights reserved. * * Author: Steven Dake (sdake@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef COROAPI_H_DEFINED #define COROAPI_H_DEFINED #include #ifdef COROSYNC_BSD #include #endif #include #include #include typedef struct { uint32_t nodeid __attribute__((aligned(8))); void *conn __attribute__((aligned(8))); } mar_message_source_t __attribute__((aligned(8))); static inline void swab_mar_message_source_t (mar_message_source_t *to_swab) { swab32 (to_swab->nodeid); /* * if it is from a byteswapped machine, then we can safely * ignore its conn info data structure since this is only * local to the machine */ to_swab->conn = NULL; } #ifndef TIMER_HANDLE_T typedef qb_loop_timer_handle corosync_timer_handle_t; #define TIMER_HANDLE_T 1 #endif struct corosync_tpg_group { const void *group; size_t group_len; }; #define TOTEMIP_ADDRLEN (sizeof(struct in6_addr)) #define INTERFACE_MAX 2 #ifdef HAVE_SMALL_MEMORY_FOOTPRINT #define PROCESSOR_COUNT_MAX 16 #define MESSAGE_SIZE_MAX 1024*64 #define MESSAGE_QUEUE_MAX 512 #else #define PROCESSOR_COUNT_MAX 384 #define MESSAGE_SIZE_MAX 1024*1024 /* (1MB) */ #define MESSAGE_QUEUE_MAX MESSAGE_SIZE_MAX / totem_config->net_mtu #endif /* HAVE_SMALL_MEMORY_FOOTPRINT */ #define TOTEM_AGREED 0 #define TOTEM_SAFE 1 #define MILLI_2_NANO_SECONDS 1000000ULL #if !defined(TOTEM_IP_ADDRESS) struct totem_ip_address { unsigned int nodeid; unsigned short family; unsigned char addr[TOTEMIP_ADDRLEN]; } __attribute__((packed)); #endif #if !defined(MEMB_RING_ID) struct memb_ring_id { struct totem_ip_address rep; unsigned long long seq; } __attribute__((packed)); #endif #if !defined(TOTEM_CONFIGURATION_TYPE) enum totem_configuration_type { TOTEM_CONFIGURATION_REGULAR, TOTEM_CONFIGURATION_TRANSITIONAL }; #endif #if !defined(TOTEM_CALLBACK_TOKEN_TYPE) enum totem_callback_token_type { TOTEM_CALLBACK_TOKEN_RECEIVED = 1, TOTEM_CALLBACK_TOKEN_SENT = 2 }; #endif enum cs_lib_flow_control { CS_LIB_FLOW_CONTROL_REQUIRED = 1, CS_LIB_FLOW_CONTROL_NOT_REQUIRED = 2 }; #define corosync_lib_flow_control cs_lib_flow_control #define COROSYNC_LIB_FLOW_CONTROL_REQUIRED CS_LIB_FLOW_CONTROL_REQUIRED #define COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED CS_LIB_FLOW_CONTROL_NOT_REQUIRED enum cs_lib_allow_inquorate { CS_LIB_DISALLOW_INQUORATE = 0, /* default */ CS_LIB_ALLOW_INQUORATE = 1 }; #if !defined (COROSYNC_FLOW_CONTROL_STATE) enum cs_flow_control_state { CS_FLOW_CONTROL_STATE_DISABLED, CS_FLOW_CONTROL_STATE_ENABLED }; #define corosync_flow_control_state cs_flow_control_state #define CS_FLOW_CONTROL_STATE_DISABLED CS_FLOW_CONTROL_STATE_DISABLED #define CS_FLOW_CONTROL_STATE_ENABLED CS_FLOW_CONTROL_STATE_ENABLED #endif /* COROSYNC_FLOW_CONTROL_STATE */ enum cs_sync_mode { CS_SYNC_V1 = 0, CS_SYNC_V2 = 1, CS_SYNC_V1_APIV2 = 2 }; typedef enum { COROSYNC_FATAL_ERROR_EXIT = -1, COROSYNC_LIBAIS_SOCKET = -6, COROSYNC_LIBAIS_BIND = -7, COROSYNC_READKEY = -8, COROSYNC_INVALID_CONFIG = -9, COROSYNC_DYNAMICLOAD = -12, COROSYNC_OUT_OF_MEMORY = -15, COROSYNC_FATAL_ERR = -16 } cs_fatal_error_t; #define corosync_fatal_error_t cs_fatal_error_t; #ifndef OBJECT_PARENT_HANDLE #define OBJECT_PARENT_HANDLE 0xffffffff00000000ULL struct object_valid { char *object_name; size_t object_len; }; struct object_key_valid { char *key_name; size_t key_len; int (*validate_callback) (const void *key, size_t key_len, const void *value, size_t value_len); }; /* deprecated */ typedef enum { OBJDB_VALUETYPE_INT16, OBJDB_VALUETYPE_UINT16, OBJDB_VALUETYPE_INT32, OBJDB_VALUETYPE_UINT32, OBJDB_VALUETYPE_INT64, OBJDB_VALUETYPE_UINT64, OBJDB_VALUETYPE_FLOAT, OBJDB_VALUETYPE_DOUBLE, OBJDB_VALUETYPE_STRING, OBJDB_VALUETYPE_ANY, } objdb_value_types_t; typedef enum { OBJECT_TRACK_DEPTH_ONE, OBJECT_TRACK_DEPTH_RECURSIVE } object_track_depth_t; typedef enum { OBJECT_KEY_CREATED, OBJECT_KEY_REPLACED, OBJECT_KEY_DELETED } object_change_type_t; typedef enum { OBJDB_RELOAD_NOTIFY_START, OBJDB_RELOAD_NOTIFY_END, OBJDB_RELOAD_NOTIFY_FAILED } objdb_reload_notify_type_t; typedef void (*object_key_change_notify_fn_t)( object_change_type_t change_type, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *object_name_pt, size_t object_name_len, const void *key_name_pt, size_t key_len, const void *key_value_pt, size_t key_value_len, void *priv_data_pt); typedef void (*object_create_notify_fn_t) ( hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *name_pt, size_t name_len, void *priv_data_pt); typedef void (*object_destroy_notify_fn_t) ( hdb_handle_t parent_object_handle, const void *name_pt, size_t name_len, void *priv_data_pt); typedef void (*object_notify_callback_fn_t)( hdb_handle_t object_handle, const void *key_name, size_t key_len, const void *value, size_t value_len, object_change_type_t type, const void * priv_data_pt); typedef void (*object_reload_notify_fn_t) ( objdb_reload_notify_type_t, int flush, void *priv_data_pt); #endif /* OBJECT_PARENT_HANDLE_DEFINED */ #ifndef QUORUM_H_DEFINED typedef void (*quorum_callback_fn_t) (int quorate, void *context); struct quorum_callin_functions { int (*quorate) (void); int (*register_callback) (quorum_callback_fn_t callback_fn, void *context); int (*unregister_callback) (quorum_callback_fn_t callback_fn, void *context); }; typedef void (*sync_callback_fn_t) ( const unsigned int *view_list, size_t view_list_entries, int primary_designated, struct memb_ring_id *ring_id); #endif /* QUORUM_H_DEFINED */ struct corosync_api_v1 { /* * Object and configuration APIs */ int (*object_create) ( hdb_handle_t parent_object_handle, hdb_handle_t *object_handle, const void *object_name, size_t object_name_len); int (*object_priv_set) ( hdb_handle_t object_handle, void *priv); int (*object_key_create) ( hdb_handle_t object_handle, const void *key_name, size_t key_len, const void *value, size_t value_len); int (*object_destroy) ( hdb_handle_t object_handle); int (*object_valid_set) ( hdb_handle_t object_handle, struct object_valid *object_valid_list, size_t object_valid_list_entries); int (*object_key_valid_set) ( hdb_handle_t object_handle, struct object_key_valid *object_key_valid_list, size_t object_key_valid_list_entries); int (*object_find_create) ( hdb_handle_t parent_object_handle, const void *object_name, size_t object_name_len, hdb_handle_t *object_find_handle); int (*object_find_next) ( hdb_handle_t object_find_handle, hdb_handle_t *object_handle); int (*object_find_destroy) ( hdb_handle_t object_find_handle); int (*object_key_get) ( hdb_handle_t object_handle, const void *key_name, size_t key_len, void **value, size_t *value_len); int (*object_priv_get) ( hdb_handle_t jobject_handle, void **priv); int (*object_key_replace) ( hdb_handle_t object_handle, const void *key_name, size_t key_len, const void *new_value, size_t new_value_len); int (*object_key_delete) ( hdb_handle_t object_handle, const void *key_name, size_t key_len); int (*object_iter_reset) ( hdb_handle_t parent_object_handle); int (*object_iter) ( hdb_handle_t parent_object_handle, void **object_name, size_t *name_len, hdb_handle_t *object_handle); int (*object_key_iter_reset) ( hdb_handle_t object_handle); int (*object_key_iter) ( hdb_handle_t parent_object_handle, void **key_name, size_t *key_len, void **value, size_t *value_len); int (*object_parent_get) ( hdb_handle_t object_handle, hdb_handle_t *parent_handle); int (*object_name_get) ( hdb_handle_t object_handle, char *object_name, size_t *object_name_len); int (*object_dump) ( hdb_handle_t object_handle, FILE *file); int (*object_key_iter_from) ( hdb_handle_t parent_object_handle, hdb_handle_t start_pos, void **key_name, size_t *key_len, void **value, size_t *value_len); int (*object_track_start) ( hdb_handle_t object_handle, object_track_depth_t depth, object_key_change_notify_fn_t key_change_notify_fn, object_create_notify_fn_t object_create_notify_fn, object_destroy_notify_fn_t object_destroy_notify_fn, object_reload_notify_fn_t object_reload_notify_fn, void * priv_data_pt); void (*object_track_stop) ( object_key_change_notify_fn_t key_change_notify_fn, object_create_notify_fn_t object_create_notify_fn, object_destroy_notify_fn_t object_destroy_notify_fn, object_reload_notify_fn_t object_reload_notify_fn, void * priv_data_pt); int (*object_write_config) (const char **error_string); int (*object_reload_config) (int flush, const char **error_string); int (*object_key_increment) ( hdb_handle_t object_handle, const void *key_name, size_t key_len, unsigned int *value); int (*object_key_decrement) ( hdb_handle_t object_handle, const void *key_name, size_t key_len, unsigned int *value); /* * Time and timer APIs */ int (*timer_add_duration) ( unsigned long long nanoseconds_in_future, void *data, void (*timer_nf) (void *data), corosync_timer_handle_t *handle); int (*timer_add_absolute) ( unsigned long long nanoseconds_from_epoch, void *data, void (*timer_fn) (void *data), corosync_timer_handle_t *handle); void (*timer_delete) ( corosync_timer_handle_t timer_handle); unsigned long long (*timer_time_get) (void); unsigned long long (*timer_expire_time_get) ( corosync_timer_handle_t timer_handle); /* * IPC APIs */ void (*ipc_source_set) (mar_message_source_t *source, void *conn); int (*ipc_source_is_local) (const mar_message_source_t *source); void *(*ipc_private_data_get) (void *conn); int (*ipc_response_send) (void *conn, const void *msg, size_t mlen); int (*ipc_response_iov_send) (void *conn, const struct iovec *iov, unsigned int iov_len); int (*ipc_dispatch_send) (void *conn, const void *msg, size_t mlen); int (*ipc_dispatch_iov_send) (void *conn, const struct iovec *iov, unsigned int iov_len); void (*ipc_refcnt_inc) (void *conn); void (*ipc_refcnt_dec) (void *conn); /* * Totem APIs */ unsigned int (*totem_nodeid_get) (void); int (*totem_family_get) (void); int (*totem_ring_reenable) (void); int (*totem_mcast) (const struct iovec *iovec, unsigned int iov_len, unsigned int guarantee); int (*totem_ifaces_get) ( unsigned int nodeid, struct totem_ip_address *interfaces, char ***status, unsigned int *iface_count); const char *(*totem_ifaces_print) (unsigned int nodeid); const char *(*totem_ip_print) (const struct totem_ip_address *addr); int (*totem_crypto_set) (unsigned int type); int (*totem_callback_token_create) ( void **handle_out, enum totem_callback_token_type type, int delete, int (*callback_fn) (enum totem_callback_token_type type, const void *), const void *data); /* * Totem open process groups API for those service engines * wanting their own groups */ int (*tpg_init) ( - hdb_handle_t *handle, + void **instance, void (*deliver_fn) ( unsigned int nodeid, const void *msg, unsigned int msg_len, int endian_conversion_required), void (*confchg_fn) ( enum totem_configuration_type configuration_type, const unsigned int *member_list, size_t member_list_entries, const unsigned int *left_list, size_t left_list_entries, const unsigned int *joined_list, size_t joined_list_entries, const struct memb_ring_id *ring_id)); int (*tpg_exit) ( - hdb_handle_t handle); + void *instance); int (*tpg_join) ( - hdb_handle_t handle, + void *instance, const struct corosync_tpg_group *groups, size_t group_cnt); int (*tpg_leave) ( - hdb_handle_t handle, + void *instance, const struct corosync_tpg_group *groups, size_t group_cnt); int (*tpg_joined_mcast) ( - hdb_handle_t handle, + void *totempg_groups_instance, const struct iovec *iovec, unsigned int iov_len, int guarantee); int (*tpg_joined_reserve) ( - hdb_handle_t handle, + void *totempg_groups_instance, const struct iovec *iovec, unsigned int iov_len); int (*tpg_joined_release) ( int reserved_msgs); int (*tpg_groups_mcast) ( - hdb_handle_t handle, + void *instance, int guarantee, const struct corosync_tpg_group *groups, size_t groups_cnt, const struct iovec *iovec, unsigned int iov_len); int (*tpg_groups_reserve) ( - hdb_handle_t handle, + void *instance, const struct corosync_tpg_group *groups, size_t groups_cnt, const struct iovec *iovec, unsigned int iov_len); int (*tpg_groups_release) ( int reserved_msgs); int (*schedwrk_create) ( hdb_handle_t *handle, int (schedwrk_fn) (const void *), const void *context); void (*schedwrk_destroy) (hdb_handle_t handle); int (*sync_request) ( const char *service_name); /* * User plugin-callable functions for quorum */ int (*quorum_is_quorate) (void); int (*quorum_register_callback) (quorum_callback_fn_t callback_fn, void *context); int (*quorum_unregister_callback) (quorum_callback_fn_t callback_fn, void *context); /* * This one is for the quorum management plugin's use */ int (*quorum_initialize)(struct quorum_callin_functions *fns); /* * Plugin loading and unloading */ int (*plugin_interface_reference) ( hdb_handle_t *handle, const char *iface_name, int version, void **interface, void *context); int (*plugin_interface_release) (hdb_handle_t handle); /* * Service loading and unloading APIs */ unsigned int (*service_link_and_init) ( struct corosync_api_v1 *corosync_api_v1, const char *service_name, unsigned int service_ver); unsigned int (*service_unlink_and_exit) ( struct corosync_api_v1 *corosync_api_v1, const char *service_name, unsigned int service_ver); /* * Error handling APIs */ void (*error_memory_failure) (void) __attribute__ ((noreturn)); #define corosync_fatal_error(err) api->fatal_error ((err), __FILE__, __LINE__) void (*fatal_error) (cs_fatal_error_t err, const char *file, unsigned int line) __attribute__ ((noreturn)); void (*shutdown_request) (void); void (*state_dump) (void); qb_loop_t *(*poll_handle_get) (void); int (*object_key_create_typed) ( hdb_handle_t object_handle, const char *key_name, const void *value, size_t value_len, objdb_value_types_t type); int (*object_key_get_typed) ( hdb_handle_t object_handle, const char *key_name, void **value, size_t *value_len, objdb_value_types_t *type); int (*object_key_iter_typed) ( hdb_handle_t parent_object_handle, char **key_name, void **value, size_t *value_len, objdb_value_types_t *type); void *(*totem_get_stats)(void); int (*schedwrk_create_nolock) ( hdb_handle_t *handle, int (schedwrk_fn) (const void *), const void *context); int (*poll_dispatch_add) (qb_loop_t * handle, int fd, int events, void *data, int (*dispatch_fn) (int fd, int revents, void *data)); int (*poll_dispatch_delete) ( qb_loop_t * handle, int fd); }; #define SERVICE_ID_MAKE(a,b) ( ((a)<<16) | (b) ) #define SERVICE_HANDLER_MAXIMUM_COUNT 64 struct corosync_lib_handler { void (*lib_handler_fn) (void *conn, const void *msg); enum cs_lib_flow_control flow_control; }; struct corosync_exec_handler { void (*exec_handler_fn) (const void *msg, unsigned int nodeid); void (*exec_endian_convert_fn) (void *msg); }; struct corosync_service_engine_iface_ver0 { struct corosync_service_engine *(*corosync_get_service_engine_ver0) (void); }; typedef void (*sync_init_v1_fn_t) ( const unsigned int *member_list, size_t member_list_entries, const struct memb_ring_id *ring_id) ; struct corosync_service_engine { const char *name; unsigned short id; unsigned short priority; /* Lower priority are loaded first, unloaded last. * 0 is a special case which always loaded _and_ unloaded last */ unsigned int private_data_size; enum cs_lib_flow_control flow_control; enum cs_lib_allow_inquorate allow_inquorate; int (*exec_init_fn) (struct corosync_api_v1 *); int (*exec_exit_fn) (void); void (*exec_dump_fn) (void); int (*lib_init_fn) (void *conn); int (*lib_exit_fn) (void *conn); struct corosync_lib_handler *lib_engine; int lib_engine_count; struct corosync_exec_handler *exec_engine; int exec_engine_count; int (*config_init_fn) (struct corosync_api_v1 *); void (*confchg_fn) ( enum totem_configuration_type configuration_type, const unsigned int *member_list, size_t member_list_entries, const unsigned int *left_list, size_t left_list_entries, const unsigned int *joined_list, size_t joined_list_entries, const struct memb_ring_id *ring_id); enum cs_sync_mode sync_mode; sync_init_v1_fn_t sync_init; int (*sync_process) (void); void (*sync_activate) (void); void (*sync_abort) (void); }; #endif /* COROAPI_H_DEFINED */