From 36df0fa194462b4d64b57be59fd98e3def9da693 Mon Sep 17 00:00:00 2001 From: "Fabio M. Di Nitto" Date: Tue, 27 Jan 2009 10:44:56 +0000 Subject: [PATCH] Update to latest svn snapshot --- ...runk-1709.diff => corosync-trunk-1750.diff | 6808 +++++++++++++++-- corosync.spec | 19 +- 2 files changed, 6272 insertions(+), 555 deletions(-) rename corosync-trunk-1709.diff => corosync-trunk-1750.diff (69%) diff --git a/corosync-trunk-1709.diff b/corosync-trunk-1750.diff similarity index 69% rename from corosync-trunk-1709.diff rename to corosync-trunk-1750.diff index 072cedc..a37d6c4 100644 --- a/corosync-trunk-1709.diff +++ b/corosync-trunk-1750.diff @@ -81,10 +81,132 @@ diff -Naurd corosync-0.92/exec/apidef.c corosync-trunk/exec/apidef.c }; void apidef_init (struct objdb_iface_ver0 *objdb) { +diff -Naurd corosync-0.92/exec/coropoll.c corosync-trunk/exec/coropoll.c +--- corosync-0.92/exec/coropoll.c 2008-08-14 18:44:26.000000000 +0200 ++++ corosync-trunk/exec/coropoll.c 2009-01-20 18:59:10.000000000 +0100 +@@ -59,6 +59,7 @@ + struct timerlist timerlist; + void (*serialize_lock_fn) (void); + void (*serialize_unlock_fn) (void); ++ int stop_requested; + }; + + /* +@@ -92,6 +93,7 @@ + poll_instance->poll_entries = 0; + poll_instance->ufds = 0; + poll_instance->poll_entry_count = 0; ++ poll_instance->stop_requested = 0; + poll_instance->serialize_lock_fn = serialize_lock_fn; + poll_instance->serialize_unlock_fn = serialize_unlock_fn; + timerlist_init (&poll_instance->timerlist); +@@ -291,18 +293,18 @@ + struct poll_instance *poll_instance; + int res = 0; + ++ if (timer_handle_out == NULL) { ++ res -ENOENT; ++ goto error_exit; ++ } ++ + res = hdb_handle_get (&poll_instance_database, handle, + (void *)&poll_instance); + if (res != 0) { + res = -ENOENT; +- + goto error_exit; + } + +- if (timer_handle_out == 0) { +- res = -ENOENT; +- } +- + timerlist_add_duration (&poll_instance->timerlist, + timer_fn, data, ((unsigned long long)msec_duration) * 1000000ULL, timer_handle_out); + +@@ -336,6 +338,27 @@ + return (res); + } + ++int poll_stop ( ++ poll_handle handle) ++{ ++ struct poll_instance *poll_instance; ++ unsigned int res; ++ ++ res = hdb_handle_get (&poll_instance_database, handle, ++ (void *)&poll_instance); ++ if (res != 0) { ++ res = -ENOENT; ++ goto error_exit; ++ } ++ ++ poll_instance->stop_requested = 1; ++ ++ hdb_handle_put (&poll_instance_database, handle); ++error_exit: ++ return (res); ++} ++ ++ + int poll_run ( + poll_handle handle) + { +@@ -366,6 +389,10 @@ + retry_poll: + res = poll (poll_instance->ufds, + poll_instance->poll_entry_count, expire_timeout_msec); ++ if (poll_instance->stop_requested) { ++ printf ("poll should stop\n"); ++ return (0); ++ } + if (errno == EINTR && res == -1) { + goto retry_poll; + } else +@@ -403,9 +430,6 @@ + return (-1); + } + +-int poll_stop ( +- poll_handle handle); +- + #ifdef COMPILE_OUT + void poll_print_state ( + poll_handle handle, diff -Naurd corosync-0.92/exec/crypto.c corosync-trunk/exec/crypto.c --- corosync-0.92/exec/crypto.c 2008-08-15 08:15:26.000000000 +0200 -+++ corosync-trunk/exec/crypto.c 2008-11-11 19:13:47.000000000 +0100 -@@ -844,7 +844,7 @@ ++++ corosync-trunk/exec/crypto.c 2009-01-26 21:22:28.000000000 +0100 +@@ -20,13 +20,14 @@ + #endif + #include + #include ++#include + + #include "crypto.h" + + #define CONST64(n) n ## ULL + +-typedef unsigned long ulong32; +-typedef unsigned long long ulong64; ++typedef uint32_t ulong32; ++typedef uint64_t ulong64; + + #if __BYTE_ORDER == __LITTLE_ENDIAN + #define ENDIAN_LITTLE +@@ -41,10 +42,10 @@ + #endif + + #if defined(COROSYNC_LINUX) +-#if __WORDIZE == 64 ++#if __WORDSIZE == 64 + #define ENDIAN_64BITWORD + #endif +-#if __WORDIZE == 32 ++#if __WORDSIZE == 32 + #define ENDIAN_32BITWORD + #endif + #else +@@ -844,7 +845,7 @@ assert ((len & 3) == 0); for (i = 0; i < len; i += 4) { @@ -93,7 +215,7 @@ diff -Naurd corosync-0.92/exec/crypto.c corosync-trunk/exec/crypto.c ADDKEY(k); cycle(c->R); XORNL(nltap(c)); -@@ -1250,11 +1250,11 @@ +@@ -1250,11 +1251,11 @@ void (*callback)(void)) { int fd; @@ -107,6 +229,27 @@ diff -Naurd corosync-0.92/exec/crypto.c corosync-trunk/exec/crypto.c close (fd); +diff -Naurd corosync-0.92/exec/crypto.h corosync-trunk/exec/crypto.h +--- corosync-0.92/exec/crypto.h 2004-09-15 22:20:07.000000000 +0200 ++++ corosync-trunk/exec/crypto.h 2009-01-26 21:22:28.000000000 +0100 +@@ -1,6 +1,8 @@ + #ifndef CRYPTO_H_DEFINED + #define CRYPTO_H_DEFINED + ++#include ++ + #define DIGEST_SHA1 0 + #define PRNG_SOBER 0 + +@@ -88,7 +90,7 @@ + unsigned char *dst, unsigned long *dstlen); + + struct sober128_prng { +- unsigned long R[17], /* Working storage for the shift register */ ++ uint32_t R[17], /* Working storage for the shift register */ + initR[17], /* saved register contents */ + konst, /* key dependent constant */ + sbuf; /* partial word encryption buffer */ diff -Naurd corosync-0.92/exec/flow.c corosync-trunk/exec/flow.c --- corosync-0.92/exec/flow.c 2008-08-14 18:54:46.000000000 +0200 +++ corosync-trunk/exec/flow.c 2008-11-06 22:49:07.000000000 +0100 @@ -361,7 +504,7 @@ diff -Naurd corosync-0.92/exec/flow.h corosync-trunk/exec/flow.h #endif /* FLOW_H_DEFINED */ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c --- corosync-0.92/exec/ipc.c 2008-09-17 21:15:00.000000000 +0200 -+++ corosync-trunk/exec/ipc.c 2008-12-08 16:55:41.000000000 +0100 ++++ corosync-trunk/exec/ipc.c 2008-12-28 10:25:17.000000000 +0100 @@ -62,7 +62,7 @@ #endif @@ -498,7 +641,29 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c } return (0); } -@@ -633,14 +634,14 @@ +@@ -486,6 +487,7 @@ + struct sched_param sched_param; + int res; + pthread_mutex_t *rel_mutex; ++ pthread_mutex_t *rel2_mutex; + unsigned int service; + struct conn_info *cinfo_partner; + void *private_data; +@@ -523,11 +525,12 @@ + + case CONN_STATE_DISCONNECTED: + rel_mutex = conn_info->shared_mutex; ++ rel2_mutex = &conn_info->mutex; + private_data = conn_info->private_data; + cinfo_partner = conn_info->conn_info_partner; + conn_info_destroy (conn); + if (service == SOCKET_SERVICE_INIT) { +- pthread_mutex_unlock (&conn_info->mutex); ++ pthread_mutex_unlock (rel2_mutex); + } else { + pthread_mutex_unlock (rel_mutex); + } +@@ -633,34 +636,37 @@ /* * IPC group-wide flow control */ @@ -513,18 +678,28 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c - corosync_flow_control_enable (conn_info->flow_control_handle); + cs_flow_control_enable (conn_info->flow_control_handle); conn_info->flow_control_enabled = 1; - conn_info->conn_info_partner->flow_control_enabled = 1; +- conn_info->conn_info_partner->flow_control_enabled = 1; ++ if (conn_info->conn_info_partner) { ++ conn_info->conn_info_partner->flow_control_enabled = 1; ++ } } -@@ -651,7 +652,7 @@ + if (conn_info->flow_control_enabled == 1 && +- + fcc <= FLOW_CONTROL_ENTRIES_DISABLE) { + log_printf (LOG_LEVEL_NOTICE, "Disabling flow control [%d/%d] - [%d].\n", entries_usedhw, SIZEQUEUE, flow_control_local_count); - corosync_flow_control_disable (conn_info->flow_control_handle); + cs_flow_control_disable (conn_info->flow_control_handle); conn_info->flow_control_enabled = 0; - conn_info->conn_info_partner->flow_control_enabled = 0; +- conn_info->conn_info_partner->flow_control_enabled = 0; ++ if (conn_info->conn_info_partner) { ++ conn_info->conn_info_partner->flow_control_enabled = 0; ++ } } -@@ -660,7 +661,7 @@ + } + } static int conn_info_outq_flush (struct conn_info *conn_info) { struct queue *outq; @@ -533,7 +708,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c struct outq_item *queue_item; struct msghdr msg_send; struct iovec iov_send; -@@ -731,14 +732,15 @@ +@@ -731,14 +737,15 @@ @@ -551,7 +726,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c mar_req_header_t *header; int service; struct msghdr msg_recv; -@@ -752,7 +754,7 @@ +@@ -752,7 +759,7 @@ int send_ok = 0; int send_ok_joined = 0; struct iovec send_ok_joined_iovec; @@ -560,7 +735,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c msg_recv.msg_iov = &iov_recv; msg_recv.msg_iovlen = 1; -@@ -841,7 +843,7 @@ +@@ -841,7 +848,7 @@ #ifdef COROSYNC_LINUX if (conn_info->authenticated == 0) { cmsg = CMSG_FIRSTHDR (&msg_recv); @@ -569,7 +744,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c cred = (struct ucred *)CMSG_DATA (cmsg); if (cred) { if (cred->uid == 0 || cred->gid == g_gid_valid) { -@@ -861,7 +863,8 @@ +@@ -861,7 +868,8 @@ conn_info->inb_inuse += res; conn_info->inb_start += res; @@ -579,7 +754,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c header = (mar_req_header_t *)&conn_info->inb[conn_info->inb_start - conn_info->inb_inuse]; if (header->size > conn_info->inb_inuse) { -@@ -874,7 +877,7 @@ +@@ -874,7 +882,7 @@ * else handle message using service service */ if (service == SOCKET_SERVICE_INIT) { @@ -588,7 +763,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c } else { /* * Not an init service, but a standard service -@@ -897,11 +900,11 @@ +@@ -897,11 +905,11 @@ &send_ok_joined_iovec, 1); send_ok = @@ -604,7 +779,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c if (send_ok) { ais_service[service]->lib_engine[header->id].lib_handler_fn(conn_info, header); -@@ -914,8 +917,8 @@ +@@ -914,8 +922,8 @@ ais_service[service]->lib_engine[header->id].response_size; res_overlay.header.id = ais_service[service]->lib_engine[header->id].response_id; @@ -615,7 +790,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c conn_info, &res_overlay, res_overlay.header.size); -@@ -1030,7 +1033,7 @@ +@@ -1030,7 +1038,7 @@ { } @@ -624,7 +799,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c void (*serialize_lock_fn) (void), void (*serialize_unlock_fn) (void), unsigned int gid_valid) -@@ -1102,7 +1105,7 @@ +@@ -1102,7 +1110,7 @@ /* * Get the conn info private data */ @@ -633,7 +808,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c { struct conn_info *conn_info = (struct conn_info *)conn; -@@ -1116,7 +1119,7 @@ +@@ -1116,7 +1124,7 @@ /* * Get the conn info partner connection */ @@ -642,7 +817,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c { struct conn_info *conn_info = (struct conn_info *)conn; -@@ -1127,25 +1130,27 @@ +@@ -1127,25 +1135,27 @@ } } @@ -674,7 +849,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c int queue_empty; struct outq_item *queue_item; struct outq_item queue_item_out; -@@ -1282,17 +1287,17 @@ +@@ -1282,17 +1292,17 @@ return (0); } @@ -695,7 +870,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c conn_info->flow_control_handle, service, id, -@@ -1302,7 +1307,7 @@ +@@ -1302,7 +1312,7 @@ conn_info->conn_info_partner->flow_control_handle = conn_info->flow_control_handle; } @@ -704,7 +879,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c void *conn, unsigned int service, unsigned char *id, -@@ -1310,14 +1315,14 @@ +@@ -1310,14 +1320,14 @@ { struct conn_info *conn_info = (struct conn_info *)conn; @@ -721,7 +896,7 @@ diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c void *conn) { struct conn_info *conn_info = (struct conn_info *)conn; -@@ -1329,7 +1334,7 @@ +@@ -1329,7 +1339,7 @@ pthread_mutex_unlock (&conn_info->flow_control_mutex); } @@ -801,12 +976,12 @@ diff -Naurd corosync-0.92/exec/ipc.h corosync-trunk/exec/ipc.h #endif /* IPC_H_DEFINED */ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c --- corosync-0.92/exec/logsys.c 2008-09-17 20:22:58.000000000 +0200 -+++ corosync-trunk/exec/logsys.c 2008-12-02 16:51:03.000000000 +0100 ++++ corosync-trunk/exec/logsys.c 2009-01-26 14:15:57.000000000 +0100 @@ -1,6 +1,6 @@ /* * Copyright (c) 2002-2004 MontaVista Software, Inc. - * Copyright (c) 2006-2007 Red Hat, Inc. -+ * Copyright (c) 2006-2008 Red Hat, Inc. ++ * Copyright (c) 2006-2009 Red Hat, Inc. * * Author: Steven Dake (sdake@redhat.com) * Author: Lon Hohberger (lhh@redhat.com) @@ -828,12 +1003,34 @@ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c #if defined(COROSYNC_LINUX) #include #endif -@@ -54,14 +58,31 @@ +@@ -54,14 +58,54 @@ #include #include -#include "wthread.h" + ++/* similar to syslog facilities/priorities tables, ++ * make a tag table for internal use ++ */ ++ ++#ifdef SYSLOG_NAMES ++CODE tagnames[] = ++ { ++ { "log", LOGSYS_TAG_LOG }, ++ { "enter", LOGSYS_TAG_ENTER }, ++ { "leave", LOGSYS_TAG_LEAVE }, ++ { "trace1", LOGSYS_TAG_TRACE1 }, ++ { "trace2", LOGSYS_TAG_TRACE2 }, ++ { "trace3", LOGSYS_TAG_TRACE3 }, ++ { "trace4", LOGSYS_TAG_TRACE4 }, ++ { "trace5", LOGSYS_TAG_TRACE5 }, ++ { "trace6", LOGSYS_TAG_TRACE6 }, ++ { "trace7", LOGSYS_TAG_TRACE7 }, ++ { "trace8", LOGSYS_TAG_TRACE8 }, ++ { NULL, -1 } ++ }; ++#endif ++ +/* + * These are not static so they can be read from the core file + */ @@ -847,6 +1044,7 @@ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c + +struct logsys_logger { + char subsys[64]; ++ unsigned int facility; + unsigned int priority; + unsigned int tags; + unsigned int mode; @@ -862,7 +1060,7 @@ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c static char *logsys_file = NULL; -@@ -69,35 +90,44 @@ +@@ -69,35 +113,44 @@ static int logsys_facility = LOG_DAEMON; @@ -925,7 +1123,7 @@ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c struct log_data { unsigned int syslog_pos; -@@ -105,324 +135,674 @@ +@@ -105,324 +158,674 @@ char *log_string; }; @@ -1163,7 +1361,7 @@ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c + /* + * Output to configured file + */ -+ if (logsys_mode & LOG_MODE_OUTPUT_FILE) { ++ if ((logsys_mode & LOG_MODE_OUTPUT_FILE) && logsys_file_fp) { + /* + * Output to a file + */ @@ -1824,7 +2022,24 @@ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c pthread_mutex_unlock (&logsys_config_mutex); } -@@ -439,7 +819,6 @@ +@@ -431,22 +834,28 @@ + return logsys_mode; + } + ++static void logsys_close_logfile() ++{ ++ if (logsys_file_fp != NULL) { ++ fclose (logsys_file_fp); ++ logsys_file_fp = NULL; ++ } ++} ++ + int logsys_config_file_set (char **error_string, char *file) + { + static char error_string_response[512]; + + if (file == NULL) { ++ logsys_close_logfile(); return (0); } @@ -1832,14 +2047,24 @@ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c pthread_mutex_lock (&logsys_config_mutex); if (logsys_mode & LOG_MODE_OUTPUT_FILE) { -@@ -454,222 +833,218 @@ + logsys_file = file; +- if (logsys_file_fp != NULL) { +- fclose (logsys_file_fp); +- } ++ logsys_close_logfile(); + logsys_file_fp = fopen (file, "a+"); + if (logsys_file_fp == 0) { + sprintf (error_string_response, +@@ -454,222 +863,243 @@ file, strerror (errno)); *error_string = error_string_response; pthread_mutex_unlock (&logsys_config_mutex); - pthread_mutex_unlock (&logsys_new_log_mutex); return (-1); } - } +- } ++ } else ++ logsys_close_logfile(); pthread_mutex_unlock (&logsys_config_mutex); - pthread_mutex_unlock (&logsys_new_log_mutex); @@ -1916,44 +2141,24 @@ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c + return (facilitynames[i].c_name); + } } -- -- logsys_wthread_active = 1; -- -- return (0); + return (NULL); - } ++} --void logsys_log_printf ( -- char *file, -- int line, -- int priority, -- char *format, -- ...) +- logsys_wthread_active = 1; +int logsys_priority_id_get (const char *name) - { -- int id = LOG_ID(priority); -- int level = LOG_LEVEL(priority); -- va_list ap; -- -- assert (id < MAX_LOGGERS); ++{ + unsigned int i; -- if (LOG_LEVEL(priority) > logsys_loggers[id].priority) { -- return; +- return (0); + for (i = 0; prioritynames[i].c_name != NULL; i++) { + if (strcasecmp(name, prioritynames[i].c_name) == 0) { + return (prioritynames[i].c_val); + } - } -- -- va_start (ap, format); -- _log_printf (LOGSYS_CONFIG_MUTEX_UNLOCKED, file, line, level, id, -- format, ap); -- va_end(ap); ++ } + return (-1); } --static void logsys_log_printf_locked ( +-void logsys_log_printf ( - char *file, - int line, - int priority, @@ -1977,41 +2182,92 @@ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c } - - va_start (ap, format); -- _log_printf (LOGSYS_CONFIG_MUTEX_LOCKED, file, line, level, id, +- _log_printf (LOGSYS_CONFIG_MUTEX_UNLOCKED, file, line, level, id, - format, ap); - va_end(ap); + return (NULL); } +-static void logsys_log_printf_locked ( +- char *file, +- int line, +- int priority, +- char *format, +- ...) ++int logsys_tag_id_get (const char *name) + { +- int id = LOG_ID(priority); +- int level = LOG_LEVEL(priority); +- va_list ap; +- +- assert (id < MAX_LOGGERS); ++ unsigned int i; + +- if (LOG_LEVEL(priority) > logsys_loggers[id].priority) { +- return; ++ for (i = 0; tagnames[i].c_name != NULL; i++) { ++ if (strcasecmp(name, tagnames[i].c_name) == 0) { ++ return (tagnames[i].c_val); ++ } + } +- +- va_start (ap, format); +- _log_printf (LOGSYS_CONFIG_MUTEX_LOCKED, file, line, level, id, +- format, ap); +- va_end(ap); ++ return (-1); + } + -void _logsys_log_printf2 ( - char *file, - int line, - int priority, - int id, - char *format, ...) -+unsigned int logsys_config_subsys_set ( -+ const char *subsys, -+ unsigned int tags, -+ unsigned int priority) ++const char *logsys_tag_name_get (unsigned int tag) { - va_list ap; -+ int i; - +- - assert (id < MAX_LOGGERS); -+ pthread_mutex_lock (&logsys_config_mutex); -+ for (i = 0; i < SUBSYS_MAX; i++) { -+ if (strcmp (logsys_loggers[i].subsys, subsys) == 0) { -+ logsys_loggers[i].tags = tags; -+ logsys_loggers[i].priority = priority; ++ unsigned int i; - va_start (ap, format); - _log_printf (LOGSYS_CONFIG_MUTEX_UNLOCKED, file, line, priority, id, - format, ap); - va_end(ap); ++ for (i = 0; tagnames[i].c_name != NULL; i++) { ++ if (tag == tagnames[i].c_val) { ++ return (tagnames[i].c_name); ++ } ++ } ++ return (NULL); + } + +-void _logsys_trace (char *file, int line, int tag, int id, char *format, ...) ++unsigned int logsys_config_subsys_set ( ++ const char *subsys, ++ unsigned int tags, ++ unsigned int priority) + { +- assert (id < MAX_LOGGERS); ++ int i; + + pthread_mutex_lock (&logsys_config_mutex); ++ for (i = 0; i < SUBSYS_MAX; i++) { ++ if (strcmp (logsys_loggers[i].subsys, subsys) == 0) { ++ logsys_loggers[i].tags = tags; ++ logsys_loggers[i].priority = priority; + +- if (tag & logsys_loggers[id].tags) { +- va_list ap; + break; + } + } -+ + +- va_start (ap, format); +- _log_printf (LOGSYS_CONFIG_MUTEX_LOCKED, file, line, +- LOG_LEVEL_DEBUG, id, format, ap); +- va_end(ap); + if (i == SUBSYS_MAX) { + for (i = 0; i < SUBSYS_MAX; i++) { + if (strcmp (logsys_loggers[i].subsys, "") == 0) { @@ -2022,31 +2278,28 @@ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c + break; + } + } -+ } + } + assert(i < SUBSYS_MAX); + -+ pthread_mutex_unlock (&logsys_config_mutex); + pthread_mutex_unlock (&logsys_config_mutex); + return i; } --void _logsys_trace (char *file, int line, int tag, int id, char *format, ...) +-static void logsys_atexit (void) +int logsys_config_subsys_get ( + const char *subsys, + unsigned int *tags, + unsigned int *priority) { -- assert (id < MAX_LOGGERS); +- if (logsys_wthread_active) { +- worker_thread_group_wait (&log_thread_group); +- } +- if (logsys_mode & LOG_MODE_OUTPUT_SYSLOG_THREADED) { +- closelog (); + unsigned int i; - - pthread_mutex_lock (&logsys_config_mutex); - -- if (tag & logsys_loggers[id].tags) { -- va_list ap; -- -- va_start (ap, format); -- _log_printf (LOGSYS_CONFIG_MUTEX_LOCKED, file, line, -- LOG_LEVEL_DEBUG, id, format, ap); -- va_end(ap); ++ ++ pthread_mutex_lock (&logsys_config_mutex); ++ + for (i = 0; i < SUBSYS_MAX; i++) { + if (strcmp (logsys_loggers[i].subsys, subsys) == 0) { + *tags = logsys_loggers[i].tags; @@ -2056,45 +2309,27 @@ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c + } } + - pthread_mutex_unlock (&logsys_config_mutex); ++ pthread_mutex_unlock (&logsys_config_mutex); + + return (-1); } --static void logsys_atexit (void) -+int logsys_log_rec_store (char *filename) - { -- if (logsys_wthread_active) { -- worker_thread_group_wait (&log_thread_group); -+ int fd; -+ ssize_t written_size; -+ size_t size_to_write = (flt_data_size + 2) * sizeof (unsigned int); -+ -+ fd = open (filename, O_CREAT|O_RDWR, 0700); -+ if (fd == -1) { -+ return (-1); - } -- if (logsys_mode & LOG_MODE_OUTPUT_SYSLOG_THREADED) { -- closelog (); -+ -+ written_size = write (fd, flt_data, size_to_write); -+ if (written_size < 0) { -+ return (-1); -+ } else if ((size_t)written_size != size_to_write) { -+ return (-1); - } -+ return (0); - } - -static void logsys_buffer_flush (void) -+static void logsys_atexit (void) ++int logsys_log_rec_store (char *filename) { - struct log_entry *entry = head; - struct log_entry *tmp; -- ++ int fd; ++ ssize_t written_size; ++ size_t size_to_write = (flt_data_size + 2) * sizeof (unsigned int); + - if (logsys_mode & LOG_MODE_FLUSH_AFTER_CONFIG) { - logsys_mode &= ~LOG_MODE_FLUSH_AFTER_CONFIG; -- ++ fd = open (filename, O_CREAT|O_RDWR, 0700); ++ if (fd == -1) { ++ return (-1); ++ } + - while (entry) { - logsys_log_printf_locked ( - entry->file, @@ -2105,13 +2340,23 @@ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c - entry = entry->next; - free (tmp); - } ++ written_size = write (fd, flt_data, size_to_write); ++ if (written_size < 0) { ++ return (-1); ++ } else if ((size_t)written_size != size_to_write) { ++ return (-1); + } ++ return (0); ++} + +- head = tail = NULL; ++static void logsys_atexit (void) ++{ + if (wthread_active) { + wthread_should_exit = 1; + wthread_signal (); + pthread_join (logsys_thread_id, NULL); - } -- -- head = tail = NULL; ++ } } -void logsys_flush (void) @@ -2184,8 +2429,17 @@ diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c - diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c --- corosync-0.92/exec/main.c 2008-08-15 08:15:26.000000000 +0200 -+++ corosync-trunk/exec/main.c 2008-12-08 16:55:41.000000000 +0100 -@@ -56,7 +56,7 @@ ++++ corosync-trunk/exec/main.c 2009-01-23 17:12:13.000000000 +0100 +@@ -34,8 +34,6 @@ + */ + #include + #include +-#include +-#include + #include + #include + #include +@@ -56,7 +54,7 @@ #include #include @@ -2194,7 +2448,7 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c #include #include #include -@@ -66,6 +66,7 @@ +@@ -66,6 +64,7 @@ #include #include @@ -2202,7 +2456,7 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c #include "totemsrp.h" #include "mempool.h" #include "mainconfig.h" -@@ -83,9 +84,11 @@ +@@ -83,18 +82,16 @@ #include "version.h" LOGSYS_DECLARE_SYSTEM ("corosync", @@ -2216,7 +2470,16 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c LOGSYS_DECLARE_SUBSYS ("MAIN", LOG_INFO); -@@ -145,7 +148,6 @@ + #define SERVER_BACKLOG 5 + +-static int ais_uid = 0; +- +-static int gid_valid = 0; +- + static unsigned int service_count = 32; + + static pthread_mutex_t serialize_mutex = PTHREAD_MUTEX_INITIALIZER; +@@ -145,7 +142,6 @@ #endif totempg_finalize (); @@ -2224,7 +2487,7 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c corosync_exit_error (AIS_DONE_EXIT); -@@ -170,15 +172,17 @@ +@@ -170,15 +166,17 @@ static void sigsegv_handler (int num) { @@ -2246,7 +2509,48 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c raise (SIGABRT); } -@@ -341,7 +345,7 @@ +@@ -271,36 +269,11 @@ + } + } + +-static void aisexec_uid_determine (struct main_config *main_config) +-{ +- struct passwd *passwd; +- +- passwd = getpwnam(main_config->user); +- if (passwd == 0) { +- log_printf (LOG_LEVEL_ERROR, "ERROR: The '%s' user is not found in /etc/passwd, please read the documentation.\n", main_config->user); +- corosync_exit_error (AIS_DONE_UID_DETERMINE); +- } +- ais_uid = passwd->pw_uid; +- endpwent (); +-} +- +-static void aisexec_gid_determine (struct main_config *main_config) +-{ +- struct group *group; +- group = getgrnam (main_config->group); +- if (group == 0) { +- log_printf (LOG_LEVEL_ERROR, "ERROR: The '%s' group is not found in /etc/group, please read the documentation.\n", group->gr_name); +- corosync_exit_error (AIS_DONE_GID_DETERMINE); +- } +- gid_valid = group->gr_gid; +- endgrent (); +-} +- +-static void aisexec_priv_drop (void) ++static void priv_drop (struct main_config *main_config) + { +-return; +- setuid (ais_uid); +- setegid (ais_uid); ++return; /* TODO: we are still not dropping privs */ ++ setuid (main_config->uid); ++ setegid (main_config->gid); + } + + static void aisexec_mempool_init (void) +@@ -341,7 +314,7 @@ } /* Create new session */ @@ -2255,7 +2559,7 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c /* * Map stdin/out/err to /dev/null. -@@ -408,7 +412,6 @@ +@@ -408,7 +381,6 @@ #endif } @@ -2263,7 +2567,7 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c static void deliver_fn ( unsigned int nodeid, struct iovec *iovec, -@@ -448,6 +451,8 @@ +@@ -448,6 +420,8 @@ */ service = header->id >> 16; fn_id = header->id & 0xffff; @@ -2272,7 +2576,7 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c if (endian_conversion_required) { assert(ais_service[service]->exec_engine[fn_id].exec_endian_convert_fn != NULL); ais_service[service]->exec_engine[fn_id].exec_endian_convert_fn -@@ -494,7 +499,6 @@ +@@ -494,7 +468,6 @@ char *iface; int res, ch; int background, setprio; @@ -2280,7 +2584,7 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c /* default configuration */ -@@ -506,7 +510,7 @@ +@@ -506,7 +479,7 @@ switch (ch) { case 'f': background = 0; @@ -2289,7 +2593,7 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c break; case 'p': setprio = 0; -@@ -527,11 +531,11 @@ +@@ -527,11 +500,11 @@ log_printf (LOG_LEVEL_NOTICE, "Copyright (C) 2002-2006 MontaVista Software, Inc and contributors.\n"); log_printf (LOG_LEVEL_NOTICE, "Copyright (C) 2006-2008 Red Hat, Inc.\n"); @@ -2306,16 +2610,22 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c corosync_timer_init ( serialize_mutex_lock, -@@ -639,6 +643,8 @@ - logsys_config_mode_set (main_config.logmode); - logsys_config_file_set (&error_string, main_config.logfile); +@@ -635,14 +608,6 @@ + corosync_exit_error (AIS_DONE_MAINCONFIGREAD); + } -+ logsys_fork_completed (); -+ - aisexec_uid_determine (&main_config); - - aisexec_gid_determine (&main_config); -@@ -654,13 +660,14 @@ +- logsys_config_facility_set ("corosync", main_config.syslog_facility); +- logsys_config_mode_set (main_config.logmode); +- logsys_config_file_set (&error_string, main_config.logfile); +- +- aisexec_uid_determine (&main_config); +- +- aisexec_gid_determine (&main_config); +- + /* + * Set round robin realtime scheduling with priority 99 + * Lock all memory to avoid page faults which may interrupt +@@ -654,13 +619,14 @@ aisexec_mlockall (); totem_config.totem_logging_configuration = totem_logging_configuration; @@ -2337,7 +2647,7 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c /* * Sleep for a while to let other nodes in the cluster -@@ -704,11 +711,9 @@ +@@ -704,11 +670,9 @@ } @@ -2351,7 +2661,12 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c /* * Drop root privleges to user 'ais' -@@ -722,7 +727,7 @@ +@@ -718,14 +682,14 @@ + * CAP_SYS_NICE (setscheduler) + * CAP_IPC_LOCK (mlockall) + */ +- aisexec_priv_drop (); ++ priv_drop (&main_config); aisexec_mempool_init (); @@ -2359,29 +2674,63 @@ diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c + cs_ipc_init ( serialize_mutex_lock, serialize_mutex_unlock, - gid_valid); +- gid_valid); ++ main_config.gid); + + /* + * Start main processing loop diff -Naurd corosync-0.92/exec/mainconfig.c corosync-trunk/exec/mainconfig.c --- corosync-0.92/exec/mainconfig.c 2008-08-14 18:54:46.000000000 +0200 -+++ corosync-trunk/exec/mainconfig.c 2008-11-06 22:49:07.000000000 +0100 -@@ -41,7 +41,7 @@ ++++ corosync-trunk/exec/mainconfig.c 2009-01-23 17:12:13.000000000 +0100 +@@ -40,8 +40,10 @@ + #include #include #include ++#include ++#include -#include +#include #include #include #include -@@ -109,8 +109,6 @@ +@@ -51,6 +53,12 @@ + #include "mempool.h" + + static char error_string_response[512]; ++static struct objdb_iface_ver0 *global_objdb; ++ ++static void add_logsys_config_notification( ++ struct objdb_iface_ver0 *objdb, ++ struct main_config *main_config); ++ + + /* This just makes the code below a little neater */ + static inline int objdb_get_string ( +@@ -98,7 +106,10 @@ + unsigned int tags; + } logsys_logger; + +-int corosync_main_config_read ( ++ ++ ++ ++int corosync_main_config_read_logging ( + struct objdb_iface_ver0 *objdb, + char **error_string, + struct main_config *main_config) +@@ -109,10 +120,6 @@ char *error_reason = error_string_response; unsigned int object_find_handle; unsigned int object_find_logsys_handle; - int global_debug = 0; - +- +- memset (main_config, 0, sizeof (struct main_config)); - memset (main_config, 0, sizeof (struct main_config)); - -@@ -120,7 +118,7 @@ + objdb->object_find_create ( + OBJECT_PARENT_HANDLE, +@@ -120,7 +127,7 @@ strlen ("logging"), &object_find_handle); @@ -2390,7 +2739,7 @@ diff -Naurd corosync-0.92/exec/mainconfig.c corosync-trunk/exec/mainconfig.c if (objdb->object_find_next ( object_find_handle, &object_service_handle) == 0) { -@@ -135,10 +133,10 @@ +@@ -135,10 +142,10 @@ } if (!objdb_get_string (objdb,object_service_handle, "to_syslog", &value)) { if (strcmp (value, "yes") == 0) { @@ -2403,7 +2752,7 @@ diff -Naurd corosync-0.92/exec/mainconfig.c corosync-trunk/exec/mainconfig.c } } if (!objdb_get_string (objdb,object_service_handle, "to_stderr", &value)) { -@@ -149,18 +147,8 @@ +@@ -149,18 +156,8 @@ main_config->logmode &= ~LOG_MODE_OUTPUT_STDERR; } } @@ -2423,11 +2772,17 @@ diff -Naurd corosync-0.92/exec/mainconfig.c corosync-trunk/exec/mainconfig.c if (strcmp (value, "on") == 0) { main_config->logmode |= LOG_MODE_DISPLAY_TIMESTAMP; } else -@@ -169,12 +157,14 @@ +@@ -169,12 +166,20 @@ } else { goto parse_error; } +*/ ++ } ++ ++ /* free old string on reload */ ++ if (main_config->logfile) { ++ free(main_config->logfile); ++ main_config->logfile = NULL; } if (!objdb_get_string (objdb,object_service_handle, "logfile", &value)) { main_config->logfile = strdup (value); @@ -2438,7 +2793,7 @@ diff -Naurd corosync-0.92/exec/mainconfig.c corosync-trunk/exec/mainconfig.c if (strcmp (value, "on") == 0) { main_config->logmode |= LOG_MODE_DISPLAY_FILELINE; } else -@@ -183,6 +173,7 @@ +@@ -183,41 +188,21 @@ } else { goto parse_error; } @@ -2446,6 +2801,260 @@ diff -Naurd corosync-0.92/exec/mainconfig.c corosync-trunk/exec/mainconfig.c } if (!objdb_get_string (objdb,object_service_handle, "syslog_facility", &value)) { +- if (strcmp (value, "daemon") == 0) { +- main_config->syslog_facility = LOG_DAEMON; +- } else +- if (strcmp (value, "local0") == 0) { +- main_config->syslog_facility = LOG_LOCAL0; +- } else +- if (strcmp (value, "local1") == 0) { +- main_config->syslog_facility = LOG_LOCAL1; +- } else +- if (strcmp (value, "local2") == 0) { +- main_config->syslog_facility = LOG_LOCAL2; +- } else +- if (strcmp (value, "local3") == 0) { +- main_config->syslog_facility = LOG_LOCAL3; +- } else +- if (strcmp (value, "local4") == 0) { +- main_config->syslog_facility = LOG_LOCAL4; +- } else +- if (strcmp (value, "local5") == 0) { +- main_config->syslog_facility = LOG_LOCAL5; +- } else +- if (strcmp (value, "local6") == 0) { +- main_config->syslog_facility = LOG_LOCAL6; +- } else +- if (strcmp (value, "local7") == 0) { +- main_config->syslog_facility = LOG_LOCAL7; +- } else { ++ main_config->syslog_facility = logsys_facility_id_get(value); ++ if (main_config->syslog_facility < 0) { + error_reason = "unknown syslog facility specified"; + goto parse_error; + } + } + ++ logsys_config_facility_set ("corosync", main_config->syslog_facility); ++ logsys_config_mode_set (main_config->logmode); ++ logsys_config_file_set (error_string, main_config->logfile); ++ + objdb->object_find_create ( + object_service_handle, + "logger_subsys", +@@ -239,6 +224,13 @@ + error_reason = "subsys required for logger directive"; + goto parse_error; + } ++ if (!objdb_get_string (objdb, object_logger_subsys_handle, "syslog_level", &value)) { ++ logsys_logger.priority = logsys_priority_id_get(value); ++ if (logsys_logger.priority < 0) { ++ error_reason = "unknown syslog priority specified"; ++ goto parse_error; ++ } ++ } + if (!objdb_get_string (objdb, object_logger_subsys_handle, "debug", &value)) { + if (strcmp (value, "on") == 0) { + logsys_logger.priority = LOG_LEVEL_DEBUG; +@@ -253,31 +245,14 @@ + char *token = strtok (value, "|"); + + while (token != NULL) { +- if (strcmp (token, "enter") == 0) { +- logsys_logger.tags |= LOGSYS_TAG_ENTER; +- } else if (strcmp (token, "leave") == 0) { +- logsys_logger.tags |= LOGSYS_TAG_LEAVE; +- } else if (strcmp (token, "trace1") == 0) { +- logsys_logger.tags |= LOGSYS_TAG_TRACE1; +- } else if (strcmp (token, "trace2") == 0) { +- logsys_logger.tags |= LOGSYS_TAG_TRACE2; +- } else if (strcmp (token, "trace3") == 0) { +- logsys_logger.tags |= LOGSYS_TAG_TRACE3; +- } else if (strcmp (token, "trace4") == 0) { +- logsys_logger.tags |= LOGSYS_TAG_TRACE4; +- } else if (strcmp (token, "trace5") == 0) { +- logsys_logger.tags |= LOGSYS_TAG_TRACE5; +- } else if (strcmp (token, "trace6") == 0) { +- logsys_logger.tags |= LOGSYS_TAG_TRACE6; +- } else if (strcmp (token, "trace7") == 0) { +- logsys_logger.tags |= LOGSYS_TAG_TRACE7; +- } else if (strcmp (token, "trace8") == 0) { +- logsys_logger.tags |= LOGSYS_TAG_TRACE8; +- } else { ++ int val; ++ ++ val = logsys_tag_id_get(token); ++ if (val < 0) { + error_reason = "bad tags value"; + goto parse_error; + } +- ++ logsys_logger.tags |= val; + token = strtok(NULL, "|"); + } + } +@@ -295,6 +270,61 @@ + + objdb->object_find_destroy (object_find_handle); + ++ return 0; ++ ++parse_error: ++ sprintf (error_string_response, ++ "parse error in config: %s.\n", ++ error_reason); ++ ++ *error_string = error_string_response; ++ return (-1); ++} ++ ++static int uid_determine (char *req_user) ++{ ++ struct passwd *passwd; ++ int ais_uid = 0; ++ ++ passwd = getpwnam(req_user); ++ if (passwd == 0) { ++ log_printf (LOG_LEVEL_ERROR, "ERROR: The '%s' user is not found in /etc/passwd, please read the documentation.\n", req_user); ++ corosync_exit_error (AIS_DONE_UID_DETERMINE); ++ } ++ ais_uid = passwd->pw_uid; ++ endpwent (); ++ return ais_uid; ++} ++ ++static int gid_determine (char *req_group) ++{ ++ struct group *group; ++ int ais_gid = 0; ++ ++ group = getgrnam (req_group); ++ if (group == 0) { ++ log_printf (LOG_LEVEL_ERROR, "ERROR: The '%s' group is not found in /etc/group, please read the documentation.\n", req_group); ++ corosync_exit_error (AIS_DONE_GID_DETERMINE); ++ } ++ ais_gid = group->gr_gid; ++ endgrent (); ++ return ais_gid; ++} ++ ++int corosync_main_config_read ( ++ struct objdb_iface_ver0 *objdb, ++ char **error_string, ++ struct main_config *main_config) ++{ ++ unsigned int object_service_handle; ++ char *value; ++ char *error_reason = error_string_response; ++ unsigned int object_find_handle; ++ ++ memset (main_config, 0, sizeof (struct main_config)); ++ ++ corosync_main_config_read_logging(objdb, error_string, main_config); ++ + objdb->object_find_create ( + OBJECT_PARENT_HANDLE, + "aisexec", +@@ -306,22 +336,18 @@ + &object_service_handle) == 0) { + + if (!objdb_get_string (objdb,object_service_handle, "user", &value)) { +- main_config->user = strdup(value); +- } ++ main_config->uid = uid_determine(value); ++ } else ++ main_config->uid = uid_determine("ais"); ++ + if (!objdb_get_string (objdb,object_service_handle, "group", &value)) { +- main_config->group = strdup(value); +- } ++ main_config->gid = gid_determine(value); ++ } else ++ main_config->gid = gid_determine("ais"); + } + + objdb->object_find_destroy (object_find_handle); + +- /* Default user/group */ +- if (!main_config->user) +- main_config->user = "ais"; +- +- if (!main_config->group) +- main_config->group = "ais"; +- + if ((main_config->logmode & LOG_MODE_OUTPUT_FILE) && + (main_config->logfile == NULL)) { + error_reason = "logmode set to 'file' but no logfile specified"; +@@ -331,6 +357,10 @@ + if (main_config->syslog_facility == 0) + main_config->syslog_facility = LOG_DAEMON; + ++ add_logsys_config_notification(objdb, main_config); ++ ++ logsys_fork_completed (); ++ + return 0; + + parse_error: +@@ -341,3 +371,38 @@ + *error_string = error_string_response; + return (-1); + } ++ ++ ++static void main_objdb_reload_notify(objdb_reload_notify_type_t type, int flush, ++ void *priv_data_pt) ++{ ++ struct main_config *main_config = priv_data_pt; ++ char *error_string; ++ ++ if (type == OBJDB_RELOAD_NOTIFY_END) { ++ ++ /* ++ * Reload the logsys configuration ++ */ ++ corosync_main_config_read_logging(global_objdb, ++ &error_string, ++ main_config); ++ } ++} ++ ++static void add_logsys_config_notification( ++ struct objdb_iface_ver0 *objdb, ++ struct main_config *main_config) ++{ ++ ++ global_objdb = objdb; ++ ++ objdb->object_track_start(OBJECT_PARENT_HANDLE, ++ 1, ++ NULL, ++ NULL, ++ NULL, ++ main_objdb_reload_notify, ++ main_config); ++ ++} +diff -Naurd corosync-0.92/exec/mainconfig.h corosync-trunk/exec/mainconfig.h +--- corosync-0.92/exec/mainconfig.h 2008-08-14 18:54:46.000000000 +0200 ++++ corosync-trunk/exec/mainconfig.h 2009-01-23 17:12:13.000000000 +0100 +@@ -61,13 +61,13 @@ + /* + * user/group to run as + */ +- char *user; +- char *group; ++ int uid; ++ int gid; + }; + + extern int corosync_main_config_read ( + struct objdb_iface_ver0 *objdb, + char **error_string, + struct main_config *main_config); +- ++ + #endif /* MAINCONFIG_H_DEFINED */ diff -Naurd corosync-0.92/exec/main.h corosync-trunk/exec/main.h --- corosync-0.92/exec/main.h 2008-08-20 02:57:40.000000000 +0200 +++ corosync-trunk/exec/main.h 2008-11-06 22:49:07.000000000 +0100 @@ -2543,7 +3152,15 @@ diff -Naurd corosync-0.92/exec/Makefile corosync-trunk/exec/Makefile diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c --- corosync-0.92/exec/objdb.c 2008-09-03 12:01:31.000000000 +0200 -+++ corosync-trunk/exec/objdb.c 2008-10-30 20:32:23.000000000 +0100 ++++ corosync-trunk/exec/objdb.c 2009-01-23 16:41:06.000000000 +0100 +@@ -1,6 +1,6 @@ + /* + * Copyright (c) 2006 MontaVista Software, Inc. +- * Copyright (c) 2007-2008 Red Hat, Inc. ++ * Copyright (c) 2007-2009 Red Hat, Inc. + * + * All rights reserved. + * @@ -59,6 +59,7 @@ object_key_change_notify_fn_t key_change_notify_fn; object_create_notify_fn_t object_create_notify_fn; @@ -2807,7 +3424,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c res = hdb_handle_get (&object_find_instance_database, object_find_handle, (void *)&object_find_instance); if (res != 0) { -@@ -714,9 +800,11 @@ +@@ -714,16 +800,35 @@ *object_handle = object_instance->object_handle; res = 0; } @@ -2819,7 +3436,31 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (-1); } -@@ -739,6 +827,7 @@ + static int object_find_destroy ( + unsigned int object_find_handle) + { ++ struct object_find_instance *object_find_instance; ++ unsigned int res; ++ ++ objdb_rdlock(); ++ res = hdb_handle_get (&object_find_instance_database, ++ object_find_handle, (void *)&object_find_instance); ++ if (res != 0) { ++ goto error_exit; ++ } ++ hdb_handle_put(&object_find_instance_database, object_find_handle); ++ hdb_handle_destroy(&object_find_instance_database, object_find_handle); ++ ++ objdb_rdunlock(); + return (0); ++ ++error_exit: ++ objdb_rdunlock(); ++ return (-1); + } + + static int object_key_get ( +@@ -739,6 +844,7 @@ struct list_head *list; int found = 0; @@ -2827,7 +3468,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { -@@ -766,9 +855,11 @@ +@@ -766,9 +872,11 @@ } hdb_handle_put (&object_instance_database, object_handle); @@ -2839,7 +3480,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (-1); } -@@ -784,6 +875,7 @@ +@@ -784,6 +892,7 @@ struct list_head *list; int found = 0; @@ -2847,7 +3488,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { -@@ -809,9 +901,11 @@ +@@ -809,9 +918,11 @@ } hdb_handle_put (&object_instance_database, object_handle); @@ -2859,7 +3500,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (-1); } -@@ -827,6 +921,7 @@ +@@ -827,6 +938,7 @@ struct list_head *list; int found = 0; @@ -2867,7 +3508,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { -@@ -852,9 +947,11 @@ +@@ -852,9 +964,11 @@ } hdb_handle_put (&object_instance_database, object_handle); @@ -2879,7 +3520,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (-1); } -@@ -872,6 +969,7 @@ +@@ -872,6 +986,7 @@ struct list_head *list; int found = 0; @@ -2887,7 +3528,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { -@@ -906,9 +1004,11 @@ +@@ -906,9 +1021,11 @@ if (ret == 0) object_key_changed_notification(object_handle, key_name, key_len, value, value_len, OBJECT_KEY_DELETED); @@ -2899,7 +3540,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (-1); } -@@ -928,6 +1028,8 @@ +@@ -928,6 +1045,8 @@ struct list_head *list; int found = 0; @@ -2908,7 +3549,33 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { -@@ -983,7 +1085,7 @@ +@@ -950,6 +1069,7 @@ + + if (found) { + int i; ++ int found_validator = 0; + + /* + * Do validation check if validation is configured for the parent object +@@ -962,7 +1082,7 @@ + instance->object_key_valid_list[i].key_name, + key_len) == 0)) { + +- found = 1; ++ found_validator = 1; + break; + } + } +@@ -970,7 +1090,7 @@ + /* + * Item not found in validation list + */ +- if (found == 0) { ++ if (found_validator == 0) { + goto error_put; + } else { + if (instance->object_key_valid_list[i].validate_callback) { +@@ -983,7 +1103,7 @@ } } @@ -2917,7 +3584,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c void *replacement_value; replacement_value = malloc(new_value_len); if (!replacement_value) -@@ -1003,11 +1105,13 @@ +@@ -1003,11 +1123,13 @@ if (ret == 0) object_key_changed_notification(object_handle, key_name, key_len, new_value, new_value_len, OBJECT_KEY_REPLACED); @@ -2931,7 +3598,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (-1); } -@@ -1018,6 +1122,7 @@ +@@ -1018,6 +1140,7 @@ int res; struct object_instance *object_instance; @@ -2939,7 +3606,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c res = hdb_handle_get (&object_instance_database, object_handle, (void *)&object_instance); if (res != 0) { -@@ -1027,9 +1132,11 @@ +@@ -1027,9 +1150,11 @@ *priv = object_instance->priv; hdb_handle_put (&object_instance_database, object_handle); @@ -2951,7 +3618,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (-1); } -@@ -1092,6 +1199,8 @@ +@@ -1092,6 +1217,8 @@ unsigned int res; struct object_instance *instance; @@ -2960,7 +3627,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { -@@ -1100,9 +1209,11 @@ +@@ -1100,9 +1227,11 @@ instance->iter_key_list = &instance->key_head; hdb_handle_put (&object_instance_database, object_handle); @@ -2972,7 +3639,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (-1); } -@@ -1119,6 +1230,8 @@ +@@ -1119,6 +1248,8 @@ struct list_head *list; unsigned int found = 0; @@ -2981,7 +3648,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c res = hdb_handle_get (&object_instance_database, parent_object_handle, (void *)&instance); if (res != 0) { -@@ -1145,9 +1258,11 @@ +@@ -1145,9 +1276,11 @@ } hdb_handle_put (&object_instance_database, parent_object_handle); @@ -2993,7 +3660,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (-1); } -@@ -1165,6 +1280,8 @@ +@@ -1165,6 +1298,8 @@ struct list_head *list; unsigned int found = 0; @@ -3002,7 +3669,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c res = hdb_handle_get (&object_instance_database, parent_object_handle, (void *)&instance); if (res != 0) { -@@ -1197,9 +1314,11 @@ +@@ -1197,9 +1332,11 @@ } hdb_handle_put (&object_instance_database, parent_object_handle); @@ -3014,7 +3681,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (-1); } -@@ -1210,9 +1329,12 @@ +@@ -1210,9 +1347,12 @@ struct object_instance *instance; unsigned int res; @@ -3027,7 +3694,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (res); } -@@ -1222,6 +1344,7 @@ +@@ -1222,6 +1362,7 @@ *parent_handle = instance->parent_handle; hdb_handle_put (&object_instance_database, object_handle); @@ -3035,7 +3702,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (0); } -@@ -1233,9 +1356,11 @@ +@@ -1233,9 +1374,11 @@ struct object_instance *instance; unsigned int res; @@ -3047,7 +3714,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (res); } -@@ -1243,6 +1368,7 @@ +@@ -1243,6 +1386,7 @@ *object_name_len = instance->object_name_len; hdb_handle_put (&object_instance_database, object_handle); @@ -3055,7 +3722,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (0); } -@@ -1253,6 +1379,7 @@ +@@ -1253,6 +1397,7 @@ 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, @@ -3063,7 +3730,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c void * priv_data_pt) { struct object_instance *instance; -@@ -1271,6 +1398,7 @@ +@@ -1271,6 +1416,7 @@ tracker_pt->key_change_notify_fn = key_change_notify_fn; tracker_pt->object_create_notify_fn = object_create_notify_fn; tracker_pt->object_destroy_notify_fn = object_destroy_notify_fn; @@ -3071,7 +3738,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c tracker_pt->data_pt = priv_data_pt; list_init(&tracker_pt->object_list); -@@ -1287,6 +1415,7 @@ +@@ -1287,6 +1433,7 @@ static 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, @@ -3079,7 +3746,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c void * priv_data_pt) { struct object_instance *instance; -@@ -1305,6 +1434,7 @@ +@@ -1305,6 +1452,7 @@ if (tracker_pt && (tracker_pt->data_pt == priv_data_pt) && (tracker_pt->object_create_notify_fn == object_create_notify_fn) && (tracker_pt->object_destroy_notify_fn == object_destroy_notify_fn) && @@ -3087,7 +3754,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c (tracker_pt->key_change_notify_fn == key_change_notify_fn)) { /* get the object & take this tracker off of it's list. */ -@@ -1337,9 +1467,11 @@ +@@ -1337,9 +1485,11 @@ struct object_instance *instance; unsigned int res; @@ -3099,7 +3766,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (res); } -@@ -1347,6 +1479,7 @@ +@@ -1347,6 +1497,7 @@ hdb_handle_put (&object_instance_database, object_handle); @@ -3107,7 +3774,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return (res); } -@@ -1358,13 +1491,19 @@ +@@ -1358,13 +1509,19 @@ int res; main_get_config_modules(&modules, &num_modules); @@ -3128,7 +3795,7 @@ diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c return 0; } -@@ -1376,14 +1515,22 @@ +@@ -1376,14 +1533,22 @@ int res; main_get_config_modules(&modules, &num_modules); @@ -3345,19 +4012,15 @@ diff -Naurd corosync-0.92/exec/quorum.h corosync-trunk/exec/quorum.h +#endif /* QUORUM_H_DEFINED */ diff -Naurd corosync-0.92/exec/service.c corosync-trunk/exec/service.c --- corosync-0.92/exec/service.c 2008-08-14 18:54:46.000000000 +0200 -+++ corosync-trunk/exec/service.c 2008-12-08 16:55:41.000000000 +0100 -@@ -78,6 +78,14 @@ ++++ corosync-trunk/exec/service.c 2009-01-27 09:59:14.000000000 +0100 +@@ -78,6 +78,10 @@ .name = "corosync_confdb", .ver = 0, }, + { + .name = "corosync_pload", + .ver = 0, -+ }, -+ { -+ .name = "corosync_quorum", -+ .ver = 0, -+ }, ++ } }; struct corosync_service_engine *ais_service[SERVICE_HANDLER_MAXIMUM_COUNT]; @@ -3838,7 +4501,7 @@ diff -Naurd corosync-0.92/exec/totemconfig.h corosync-trunk/exec/totemconfig.h #include diff -Naurd corosync-0.92/exec/totemip.c corosync-trunk/exec/totemip.c --- corosync-0.92/exec/totemip.c 2008-09-16 17:35:09.000000000 +0200 -+++ corosync-trunk/exec/totemip.c 2008-12-02 15:50:51.000000000 +0100 ++++ corosync-trunk/exec/totemip.c 2009-01-26 21:46:45.000000000 +0100 @@ -226,7 +226,7 @@ sin->sin_len = sizeof(struct sockaddr_in); #endif @@ -3857,7 +4520,17 @@ diff -Naurd corosync-0.92/exec/totemip.c corosync-trunk/exec/totemip.c sin->sin6_scope_id = 2; memcpy(&sin->sin6_addr, ip_addr->addr, sizeof(struct in6_addr)); -@@ -472,7 +472,7 @@ +@@ -376,7 +376,8 @@ + int totemip_iface_check(struct totem_ip_address *bindnet, + struct totem_ip_address *boundto, + int *interface_up, +- int *interface_num) ++ int *interface_num, ++ int mask_high_bit) + { + int fd; + struct { +@@ -472,7 +473,7 @@ memcpy(&network, RTA_DATA(tb[IFA_BROADCAST]), sizeof(uint32_t)); memcpy(&addr, bindnet->addr, sizeof(uint32_t)); @@ -3866,6 +4539,25 @@ diff -Naurd corosync-0.92/exec/totemip.c corosync-trunk/exec/totemip.c memcpy(ipaddr.addr, RTA_DATA(tb[IFA_ADDRESS]), TOTEMIP_ADDRLEN); found_if = 1; } +@@ -514,6 +515,18 @@ + } + } + finished: ++ /* ++ * Mask 32nd bit off to workaround bugs in other poeples code ++ * if configuration requests it. ++ */ ++ if (ipaddr.family == AF_INET && ipaddr.nodeid == 0) { ++ unsigned int nodeid = 0; ++ memcpy (&nodeid, ipaddr.addr, sizeof (int)); ++ if (mask_high_bit) { ++ nodeid &= 0x7FFFFFFF; ++ } ++ ipaddr.nodeid = nodeid; ++ } + totemip_copy (boundto, &ipaddr); + close(fd); + return 0; diff -Naurd corosync-0.92/exec/totemmrp.c corosync-trunk/exec/totemmrp.c --- corosync-0.92/exec/totemmrp.c 2008-08-14 18:44:26.000000000 +0200 +++ corosync-trunk/exec/totemmrp.c 2008-12-01 19:44:55.000000000 +0100 @@ -3880,7 +4572,7 @@ diff -Naurd corosync-0.92/exec/totemmrp.c corosync-trunk/exec/totemmrp.c } diff -Naurd corosync-0.92/exec/totemnet.c corosync-trunk/exec/totemnet.c --- corosync-0.92/exec/totemnet.c 2008-08-14 18:44:26.000000000 +0200 -+++ corosync-trunk/exec/totemnet.c 2008-10-30 23:25:56.000000000 +0100 ++++ corosync-trunk/exec/totemnet.c 2009-01-25 22:15:25.000000000 +0100 @@ -137,7 +137,11 @@ int totemnet_log_level_debug; @@ -3909,7 +4601,28 @@ diff -Naurd corosync-0.92/exec/totemnet.c corosync-trunk/exec/totemnet.c static int authenticate_and_decrypt ( struct totemnet_instance *instance, -@@ -1192,6 +1200,7 @@ +@@ -691,18 +699,9 @@ + int res; + + res = totemip_iface_check (bindnet, bound_to, +- interface_up, interface_num); ++ interface_up, interface_num, +++ 0); // TODO andrew can address this instance->totem_config->clear_node_high_bit); + +- /* +- * If the desired binding is to an IPV4 network and nodeid isn't +- * specified, retrieve the node id from this_ip network address +- * +- * IPV6 networks must have a node ID specified since the node id +- * field is only 32 bits. +- */ +- if (bound_to->family == AF_INET && bound_to->nodeid == 0) { +- memcpy (&bound_to->nodeid, bound_to->addr, sizeof (int)); +- } + + return (res); + } +@@ -1192,6 +1191,7 @@ instance->totemnet_log_level_warning = totem_config->totem_logging_configuration.log_level_warning; instance->totemnet_log_level_notice = totem_config->totem_logging_configuration.log_level_notice; instance->totemnet_log_level_debug = totem_config->totem_logging_configuration.log_level_debug; @@ -3919,7 +4632,7 @@ diff -Naurd corosync-0.92/exec/totemnet.c corosync-trunk/exec/totemnet.c /* diff -Naurd corosync-0.92/exec/totempg.c corosync-trunk/exec/totempg.c --- corosync-0.92/exec/totempg.c 2008-08-14 18:44:26.000000000 +0200 -+++ corosync-trunk/exec/totempg.c 2008-12-01 19:44:55.000000000 +0100 ++++ corosync-trunk/exec/totempg.c 2009-01-25 22:25:25.000000000 +0100 @@ -153,7 +153,10 @@ static int totempg_log_level_warning; static int totempg_log_level_notice; @@ -3932,7 +4645,21 @@ diff -Naurd corosync-0.92/exec/totempg.c corosync-trunk/exec/totempg.c struct totem_config *totempg_totem_config; -@@ -225,8 +228,11 @@ +@@ -165,6 +168,13 @@ + struct list_head list; + }; + ++enum throw_away_mode_t { ++ THROW_AWAY_INACTIVE, ++ THROW_AWAY_ACTIVE ++}; ++ ++static enum throw_away_mode_t throw_away_mode = THROW_AWAY_INACTIVE; ++ + DECLARE_LIST_INIT(assembly_list_inuse); + + DECLARE_LIST_INIT(assembly_list_free); +@@ -225,8 +235,11 @@ static pthread_mutex_t mcast_msg_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -3946,7 +4673,78 @@ diff -Naurd corosync-0.92/exec/totempg.c corosync-trunk/exec/totempg.c static struct assembly *assembly_ref (unsigned int nodeid) { -@@ -686,6 +692,7 @@ +@@ -558,43 +571,32 @@ + * the continued message. + */ + start = 0; +- if (continuation) { + +- if (continuation != assembly->last_frag_num) { +- log_printf (totempg_log_level_error, +- "Message continuation doesn't match previous frag e: %u - a: %u\n", +- assembly->last_frag_num, continuation); +- continuation = 0; +- } ++ if (throw_away_mode == THROW_AWAY_ACTIVE) { ++ /* Throw away the first msg block */ ++ if (mcast->fragmented == 0 || mcast->fragmented == 1) { ++ throw_away_mode = THROW_AWAY_INACTIVE; + +- if ((assembly->index == 0) || +- (!continuation && assembly->index)) { +- log_printf (totempg_log_level_error, +- "Throwing away broken message: continuation %u, index %u\n", +- continuation, assembly->index); +- continuation = 0; +- } +- +- /* +- * we decided to throw away the first continued message +- * in this buffer, if continuation was set to zero. +- */ +- if (!continuation) { + assembly->index += msg_lens[0]; + iov_delv.iov_base = &assembly->data[assembly->index]; + iov_delv.iov_len = msg_lens[1]; + start = 1; + } +- +- } +- +- for (i = start; i < msg_count; i++) { +- app_deliver_fn(nodeid, &iov_delv, 1, +- endian_conversion_required); +- assembly->index += msg_lens[i]; +- iov_delv.iov_base = &assembly->data[assembly->index]; +- if (i < (msg_count - 1)) { +- iov_delv.iov_len = msg_lens[i + 1]; ++ } else ++ if (throw_away_mode == THROW_AWAY_INACTIVE) { ++ if (continuation == assembly->last_frag_num) { ++ assembly->last_frag_num = mcast->fragmented; ++ for (i = start; i < msg_count; i++) { ++ app_deliver_fn(nodeid, &iov_delv, 1, ++ endian_conversion_required); ++ assembly->index += msg_lens[i]; ++ iov_delv.iov_base = &assembly->data[assembly->index]; ++ if (i < (msg_count - 1)) { ++ iov_delv.iov_len = msg_lens[i + 1]; ++ } ++ } ++ } else { ++ throw_away_mode = THROW_AWAY_ACTIVE; + } + } + +@@ -609,7 +611,6 @@ + /* + * Message is fragmented, keep around assembly list + */ +- assembly->last_frag_num = mcast->fragmented; + if (mcast->msg_count > 1) { + memmove (&assembly->data[0], + &assembly->data[assembly->index], +@@ -686,6 +687,7 @@ totempg_log_level_notice = totem_config->totem_logging_configuration.log_level_notice; totempg_log_level_debug = totem_config->totem_logging_configuration.log_level_debug; totempg_log_printf = totem_config->totem_logging_configuration.log_printf; @@ -3954,7 +4752,7 @@ diff -Naurd corosync-0.92/exec/totempg.c corosync-trunk/exec/totempg.c fragmentation_data = malloc (TOTEMPG_PACKET_SIZE); if (fragmentation_data == 0) { -@@ -721,14 +728,16 @@ +@@ -721,14 +723,16 @@ * Multicast a message */ static int mcast_msg ( @@ -3972,7 +4770,7 @@ diff -Naurd corosync-0.92/exec/totempg.c corosync-trunk/exec/totempg.c int max_packet_size = 0; int copy_len = 0; int copy_base = 0; -@@ -737,6 +746,18 @@ +@@ -737,6 +741,18 @@ pthread_mutex_lock (&mcast_msg_mutex); totemmrp_new_msg_signal (); @@ -3991,7 +4789,15 @@ diff -Naurd corosync-0.92/exec/totempg.c corosync-trunk/exec/totempg.c max_packet_size = TOTEMPG_PACKET_SIZE - (sizeof (unsigned short) * (mcast_packed_msg_count + 1)); -@@ -1243,7 +1264,7 @@ +@@ -774,6 +790,7 @@ + iovec[i].iov_base + copy_base, copy_len); + fragment_size += copy_len; + mcast_packed_msg_lens[mcast_packed_msg_count] += copy_len; ++ next_fragment = 1; + copy_len = 0; + copy_base = 0; + i++; +@@ -1243,7 +1260,7 @@ return (iface_string); } @@ -4043,7 +4849,7 @@ diff -Naurd corosync-0.92/exec/totemrrp.c corosync-trunk/exec/totemrrp.c instance->interfaces = totem_config->interfaces; diff -Naurd corosync-0.92/exec/totemsrp.c corosync-trunk/exec/totemsrp.c --- corosync-0.92/exec/totemsrp.c 2008-08-20 03:07:29.000000000 +0200 -+++ corosync-trunk/exec/totemsrp.c 2008-12-01 19:44:55.000000000 +0100 ++++ corosync-trunk/exec/totemsrp.c 2009-01-20 18:41:45.000000000 +0100 @@ -429,7 +429,11 @@ int totemsrp_log_level_debug; @@ -4163,6 +4969,15 @@ diff -Naurd corosync-0.92/exec/totemsrp.c corosync-trunk/exec/totemsrp.c commit_token->header.nodeid = instance->my_id.addr[0].nodeid; commit_token->memb_index += 1; assert (commit_token->memb_index <= commit_token->addr_entries); +@@ -2944,6 +2986,8 @@ + goto error_exit; + } + ++ token_hold_cancel_send (instance); ++ + callback_handle = (struct token_callback_instance *)malloc (sizeof (struct token_callback_instance)); + if (callback_handle == 0) { + return (-1); diff -Naurd corosync-0.92/exec/totemsrp.h corosync-trunk/exec/totemsrp.h --- corosync-0.92/exec/totemsrp.h 2008-08-14 18:44:26.000000000 +0200 +++ corosync-trunk/exec/totemsrp.h 2008-12-01 19:44:55.000000000 +0100 @@ -4177,7 +4992,7 @@ diff -Naurd corosync-0.92/exec/totemsrp.h corosync-trunk/exec/totemsrp.h extern int totemsrp_my_family_get ( diff -Naurd corosync-0.92/exec/util.c corosync-trunk/exec/util.c --- corosync-0.92/exec/util.c 2008-09-17 21:04:19.000000000 +0200 -+++ corosync-trunk/exec/util.c 2008-11-06 22:49:07.000000000 +0100 ++++ corosync-trunk/exec/util.c 2008-12-18 09:28:46.000000000 +0100 @@ -39,7 +39,7 @@ #include #include @@ -4223,7 +5038,8 @@ diff -Naurd corosync-0.92/exec/util.c corosync-trunk/exec/util.c log_printf (LOG_LEVEL_ERROR, "AIS Executive exiting " "with status %d at %s:%u.\n", err, file, line); - logsys_flush(); - exit (EXIT_FAILURE); +- exit (EXIT_FAILURE); ++ exit (err); } #define min(a,b) ((a) < (b) ? (a) : (b)) @@ -4323,8 +5139,8 @@ diff -Naurd corosync-0.92/exec/vsf.h corosync-trunk/exec/vsf.h int view_list_entries, diff -Naurd corosync-0.92/exec/vsf_quorum.c corosync-trunk/exec/vsf_quorum.c --- corosync-0.92/exec/vsf_quorum.c 1970-01-01 01:00:00.000000000 +0100 -+++ corosync-trunk/exec/vsf_quorum.c 2008-12-08 16:55:41.000000000 +0100 -@@ -0,0 +1,462 @@ ++++ corosync-trunk/exec/vsf_quorum.c 2009-01-08 12:12:10.000000000 +0100 +@@ -0,0 +1,468 @@ +/* + * Copyright (c) 2008 Red Hat, Inc. + * @@ -4630,6 +5446,12 @@ diff -Naurd corosync-0.92/exec/vsf_quorum.c corosync-trunk/exec/vsf_quorum.c + quorum_iface->init (api, quorum_api_set_quorum); + } + } ++ if (!quorum_iface) { ++ /* ++ * With no quorum provider, we are always quorate ++ */ ++ primary_designated = 1; ++ } + + return (0); +} @@ -5031,8 +5853,16 @@ diff -Naurd corosync-0.92/include/corosync/ais_util.h corosync-trunk/include/cor #endif /* AIS_UTIL_H_DEFINED */ diff -Naurd corosync-0.92/include/corosync/cfg.h corosync-trunk/include/corosync/cfg.h --- corosync-0.92/include/corosync/cfg.h 2008-08-15 08:15:26.000000000 +0200 -+++ corosync-trunk/include/corosync/cfg.h 2008-11-06 22:49:07.000000000 +0100 -@@ -36,9 +36,9 @@ ++++ corosync-trunk/include/corosync/cfg.h 2009-01-19 09:31:21.000000000 +0100 +@@ -1,6 +1,6 @@ + /* + * Copyright (c) 2005 MontaVista Software, Inc. +- * Copyright (c) 2006 Red Hat, Inc. ++ * Copyright (c) 2006-2009 Red Hat, Inc. + * + * All rights reserved. + * +@@ -36,33 +36,33 @@ #define AIS_COROSYNCCFG_H_DEFINED #include @@ -5044,10 +5874,50 @@ diff -Naurd corosync-0.92/include/corosync/cfg.h corosync-trunk/include/corosync typedef enum { COROSYNC_CFG_ADMINISTRATIVETARGET_SERVICEUNIT = 0, -@@ -82,24 +82,46 @@ - COROSYNC_CFG_STATETYPE_PRESENCE = 4 - } CorosyncCfgStateTypeT; + COROSYNC_CFG_ADMINISTRATIVETARGET_SERVICEGROUP = 1, + COROSYNC_CFG_ADMINISTRATIVETARGET_COMPONENTSERVICEINSTANCE = 2, + COROSYNC_CFG_ADMINISTRATIVETARGET_NODE = 3 +-} CorosyncCfgAdministrativeTargetT; ++} corosync_cfg_administrative_target_t; + typedef enum { + COROSYNC_CFG_ADMINISTRATIVESTATE_UNLOCKED = 0, + COROSYNC_CFG_ADMINISTRATIVESTATE_LOCKED = 1, + COROSYNC_CFG_ADMINISTRATIVESTATE_STOPPING = 2 +-} CorosyncCfgAdministrativeStateT; ++} corosync_cfg_administrative_state_t; + + typedef enum { + COROSYNC_CFG_OPERATIONALSTATE_ENABLED = 1, + COROSYNC_CFG_OPERATIONALSTATE_DISABLED = 2 +-} CorosyncCfgOperationalStateT; ++} corosync_cfg_operational_state_t; + + typedef enum { + COROSYNC_CFG_READINESSSTATE_OUTOFSERVICE = 1, + COROSYNC_CFG_READINESSSTATE_INSERVICE = 2, + COROSYNC_CFG_READINESSSTATE_STOPPING = 3 +-} CorosyncCfgReadinessStateT; ++} corosync_cfg_readiness_state_t; + + typedef enum { + COROSYNC_CFG_PRESENCESTATE_UNINSTANTIATED = 1, +@@ -72,7 +72,7 @@ + COROSYNC_CFG_PRESENCESTATE_RESTARTING = 5, + COROSYNC_CFG_PRESENCESTATE_INSTANTIATION_FAILED = 6, + COROSYNC_CFG_PRESENCESTATE_TERMINATION_FAILED = 7 +-} CorosyncCfgPresenceStateT; ++} corosync_cfg_presence_state_t; + + typedef enum { + COROSYNC_CFG_STATETYPE_OPERATIONAL = 0, +@@ -80,27 +80,63 @@ + COROSYNC_CFG_STATETYPE_READINESS = 2, + COROSYNC_CFG_STATETYPE_HA = 3, + COROSYNC_CFG_STATETYPE_PRESENCE = 4 +-} CorosyncCfgStateTypeT; ++} corosync_cfg_state_type_t; ++ +/* Shutdown types. + REQUEST is the normal shutdown. other daemons will be consulted + REGARDLESS will tell other daemons but ignore their opinions @@ -5057,44 +5927,69 @@ diff -Naurd corosync-0.92/include/corosync/cfg.h corosync-trunk/include/corosync + COROSYNC_CFG_SHUTDOWN_FLAG_REQUEST = 0, + COROSYNC_CFG_SHUTDOWN_FLAG_REGARDLESS = 1, + COROSYNC_CFG_SHUTDOWN_FLAG_IMMEDIATE = 2, -+} CorosyncCfgShutdownFlagsT; ++} corosync_cfg_shutdown_flags_t; + +typedef enum { + COROSYNC_CFG_SHUTDOWN_FLAG_NO = 0, + COROSYNC_CFG_SHUTDOWN_FLAG_YES = 1, -+} CorosyncCfgShutdownReplyFlagsT; -+ ++} corosync_cfg_shutdown_reply_flags_t; + typedef struct { - SaNameT name; +- CorosyncCfgStateTypeT stateType; +- CorosyncCfgAdministrativeStateT administrativeState; +-} CorosyncCfgStateNotificationT; + cs_name_t name; - CorosyncCfgStateTypeT stateType; - CorosyncCfgAdministrativeStateT administrativeState; - } CorosyncCfgStateNotificationT; ++ corosync_cfg_state_type_t state_type; ++ corosync_cfg_administrative_state_t administrative_state; ++} corosync_cfg_state_notification_t; typedef struct { - SaUint32T numberOfItems; -+ uint32_t numberOfItems; - CorosyncCfgStateNotificationT *notification; - } CorosyncCfgStateNotificationBufferT; +- CorosyncCfgStateNotificationT *notification; +-} CorosyncCfgStateNotificationBufferT; ++ uint32_t number_of_items; ++ corosync_cfg_state_notification_t *notification; ++} corosync_cfg_state_notification_buffer_t; - typedef void (*CorosyncCfgStateTrackCallbackT) ( - CorosyncCfgStateNotificationBufferT *notificationBuffer, +-typedef void (*CorosyncCfgStateTrackCallbackT) ( +- CorosyncCfgStateNotificationBufferT *notificationBuffer, - SaAisErrorT error); ++typedef void (*corosync_cfg_state_track_callback_t) ( ++ corosync_cfg_state_notification_buffer_t *notification_buffer, + cs_error_t error); + -+typedef void (*CorosyncCfgShutdownCallbackT) ( ++typedef void (*corosync_cfg_shutdown_callback_t) ( + corosync_cfg_handle_t cfg_handle, -+ CorosyncCfgShutdownFlagsT flags); ++ corosync_cfg_shutdown_flags_t flags); typedef struct { - CorosyncCfgStateTrackCallbackT - corosyncCfgStateTrackCallback; -+ CorosyncCfgShutdownCallbackT -+ corosyncCfgShutdownCallback; - } CorosyncCfgCallbacksT; +- CorosyncCfgStateTrackCallbackT +- corosyncCfgStateTrackCallback; +-} CorosyncCfgCallbacksT; ++ corosync_cfg_state_track_callback_t corosync_cfg_state_track_callback; ++ corosync_cfg_shutdown_callback_t corosync_cfg_shutdown_callback; ++} corosync_cfg_callbacks_t; ++ ++/* ++ * A node address. This is a complete sockaddr_in[6] ++ * To explain: ++ * If you cast cna_address to a 'struct sockaddr', the sa_family field ++ * will be AF_INET or AF_INET6. Armed with that knowledge you can then ++ * cast it to a sockaddr_in or sockaddr_in6 and pull out the address. ++ * No other sockaddr fields are valid. ++ * Also, you must ignore any part of the sockaddr beyond the length supplied ++ */ ++typedef struct ++{ ++ int addressLength; ++ char address[sizeof(struct sockaddr_in6)]; ++} corosync_cfg_node_address_t; ++ /* -@@ -109,67 +131,84 @@ + * Interfaces +@@ -109,70 +145,97 @@ extern "C" { #endif @@ -5102,7 +5997,8 @@ diff -Naurd corosync-0.92/include/corosync/cfg.h corosync-trunk/include/corosync +cs_error_t corosync_cfg_initialize ( corosync_cfg_handle_t *cfg_handle, - const CorosyncCfgCallbacksT *cfgCallbacks); +- const CorosyncCfgCallbacksT *cfgCallbacks); ++ const corosync_cfg_callbacks_t *cfg_callbacks); -SaAisErrorT +cs_error_t @@ -5116,7 +6012,7 @@ diff -Naurd corosync-0.92/include/corosync/cfg.h corosync-trunk/include/corosync corosync_cfg_dispatch ( corosync_cfg_handle_t cfg_handle, - SaDispatchFlagsT dispatchFlags); -+ cs_dispatch_flags_t dispatchFlags); ++ cs_dispatch_flags_t dispatch_flags); -SaAisErrorT +cs_error_t @@ -5154,15 +6050,19 @@ diff -Naurd corosync-0.92/include/corosync/cfg.h corosync-trunk/include/corosync +cs_error_t corosync_cfg_administrative_state_get ( corosync_cfg_handle_t cfg_handle, - CorosyncCfgAdministrativeTargetT administrativeTarget, - CorosyncCfgAdministrativeStateT *administrativeState); +- CorosyncCfgAdministrativeTargetT administrativeTarget, +- CorosyncCfgAdministrativeStateT *administrativeState); ++ corosync_cfg_administrative_target_t administrative_target, ++ corosync_cfg_administrative_state_t *administrative_state); -SaAisErrorT +cs_error_t corosync_cfg_administrative_state_set ( corosync_cfg_handle_t cfg_handle, - CorosyncCfgAdministrativeTargetT administrativeTarget, - CorosyncCfgAdministrativeStateT administrativeState); +- CorosyncCfgAdministrativeTargetT administrativeTarget, +- CorosyncCfgAdministrativeStateT administrativeState); ++ corosync_cfg_administrative_target_t administrative_target, ++ corosync_cfg_administrative_state_t administrative_state); -SaAisErrorT +cs_error_t @@ -5174,26 +6074,40 @@ diff -Naurd corosync-0.92/include/corosync/cfg.h corosync-trunk/include/corosync +cs_error_t +corosync_cfg_try_shutdown ( + corosync_cfg_handle_t cfg_handle, -+ CorosyncCfgShutdownFlagsT flags); ++ corosync_cfg_shutdown_flags_t flags); + + +cs_error_t +corosync_cfg_replyto_shutdown ( + corosync_cfg_handle_t cfg_handle, -+ CorosyncCfgShutdownReplyFlagsT flags); ++ corosync_cfg_shutdown_reply_flags_t flags); + +cs_error_t corosync_cfg_state_track ( corosync_cfg_handle_t cfg_handle, - SaUint8T trackFlags, -+ uint8_t trackFlags, - const CorosyncCfgStateNotificationT *notificationBuffer); +- const CorosyncCfgStateNotificationT *notificationBuffer); ++ uint8_t track_flags, ++ const corosync_cfg_state_notification_t *notification_buffer); -SaAisErrorT +cs_error_t corosync_cfg_state_track_stop ( corosync_cfg_handle_t cfg_handle); ++ ++cs_error_t ++corosync_cfg_get_node_addrs ( ++ corosync_cfg_handle_t cfg_handle, ++ int nodeid, ++ int max_addrs, ++ int *num_addrs, ++ corosync_cfg_node_address_t *addrs); ++ ++ + #ifdef __cplusplus + } + #endif diff -Naurd corosync-0.92/include/corosync/confdb.h corosync-trunk/include/corosync/confdb.h --- corosync-0.92/include/corosync/confdb.h 2008-09-03 09:58:08.000000000 +0200 +++ corosync-trunk/include/corosync/confdb.h 2008-11-06 22:49:07.000000000 +0100 @@ -5762,7 +6676,7 @@ diff -Naurd corosync-0.92/include/corosync/cpg.h corosync-trunk/include/corosync diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/include/corosync/engine/coroapi.h --- corosync-0.92/include/corosync/engine/coroapi.h 2008-09-17 21:15:00.000000000 +0200 -+++ corosync-trunk/include/corosync/engine/coroapi.h 2008-12-08 16:55:41.000000000 +0100 ++++ corosync-trunk/include/corosync/engine/coroapi.h 2009-01-20 14:19:05.000000000 +0100 @@ -41,7 +41,7 @@ typedef void * corosync_timer_handle_t; @@ -5834,19 +6748,20 @@ diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/inclu typedef enum { OBJECT_TRACK_DEPTH_ONE, -@@ -137,6 +158,11 @@ +@@ -137,6 +158,12 @@ OBJECT_KEY_DELETED } object_change_type_t; +typedef enum { + OBJDB_RELOAD_NOTIFY_START, -+ OBJDB_RELOAD_NOTIFY_END ++ 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, unsigned int parent_object_handle, unsigned int object_handle, -@@ -159,8 +185,30 @@ +@@ -159,8 +186,30 @@ object_change_type_t type, void * priv_data_pt); @@ -5877,7 +6792,7 @@ diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/inclu struct corosync_api_v1 { /* * Object and configuration APIs -@@ -280,12 +328,14 @@ +@@ -280,12 +329,14 @@ 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, @@ -5892,7 +6807,7 @@ diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/inclu void * priv_data_pt); int (*object_write_config) (char **error_string); -@@ -357,7 +407,7 @@ +@@ -357,7 +408,7 @@ int id_len, void (*flow_control_state_set_fn) (void *context, @@ -5901,7 +6816,7 @@ diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/inclu void *context); void (*ipc_fc_destroy) ( -@@ -373,7 +423,7 @@ +@@ -373,7 +424,7 @@ /* * Totem APIs */ @@ -5910,7 +6825,7 @@ diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/inclu int (*totem_family_get) (void); -@@ -393,12 +443,20 @@ +@@ -393,12 +444,20 @@ char *(*totem_ip_print) (struct totem_ip_address *addr); @@ -5932,7 +6847,7 @@ diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/inclu void (*deliver_fn) ( unsigned int nodeid, -@@ -414,31 +472,31 @@ +@@ -414,31 +473,31 @@ struct memb_ring_id *ring_id)); int (*tpg_exit) ( @@ -5970,7 +6885,7 @@ diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/inclu int guarantee, struct corosync_tpg_group *groups, int groups_cnt, -@@ -446,7 +504,7 @@ +@@ -446,7 +505,7 @@ int iov_len); int (*tpg_groups_send_ok) ( @@ -5979,7 +6894,7 @@ diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/inclu struct corosync_tpg_group *groups, int groups_cnt, struct iovec *iovec, -@@ -456,6 +514,19 @@ +@@ -456,6 +515,19 @@ char *service_name); /* @@ -5999,7 +6914,7 @@ diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/inclu * Plugin loading and unloading */ int (*plugin_interface_reference) ( -@@ -485,7 +556,7 @@ +@@ -485,7 +557,7 @@ */ void (*error_memory_failure) (void); #define corosync_fatal_error(err) api->fatal_error ((err), __FILE__, __LINE__) @@ -6008,7 +6923,7 @@ diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/inclu }; #define SERVICE_ID_MAKE(a,b) ( ((a)<<16) | (b) ) -@@ -496,7 +567,7 @@ +@@ -496,7 +568,7 @@ void (*lib_handler_fn) (void *conn, void *msg); int response_size; int response_id; @@ -6017,7 +6932,7 @@ diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/inclu }; struct corosync_exec_handler { -@@ -512,7 +583,8 @@ +@@ -512,7 +584,8 @@ char *name; unsigned short id; unsigned int private_data_size; @@ -6029,7 +6944,7 @@ diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/inclu void (*exec_dump_fn) (void); diff -Naurd corosync-0.92/include/corosync/engine/logsys.h corosync-trunk/include/corosync/engine/logsys.h --- corosync-0.92/include/corosync/engine/logsys.h 2008-08-14 18:54:46.000000000 +0200 -+++ corosync-trunk/include/corosync/engine/logsys.h 2008-10-30 23:25:56.000000000 +0100 ++++ corosync-trunk/include/corosync/engine/logsys.h 2009-01-16 09:59:09.000000000 +0100 @@ -1,6 +1,6 @@ /* * Copyright (c) 2002-2004 MontaVista Software, Inc. @@ -6126,10 +7041,16 @@ diff -Naurd corosync-0.92/include/corosync/engine/logsys.h corosync-trunk/includ extern unsigned int logsys_config_subsys_set ( const char *subsys, unsigned int tags, -@@ -137,33 +119,54 @@ +@@ -137,33 +119,60 @@ extern const char *logsys_priority_name_get ( unsigned int priority); ++extern int logsys_tag_id_get ( ++ const char *name); ++ ++extern const char *logsys_tag_name_get ( ++ unsigned int tag); ++ +extern void logsys_fork_completed (void); + extern void logsys_flush (void); @@ -6190,7 +7111,7 @@ diff -Naurd corosync-0.92/include/corosync/engine/logsys.h corosync-trunk/includ __attribute__ ((constructor)) static void logsys_system_init (void) \ { \ char *error_string; \ -@@ -171,13 +174,11 @@ +@@ -171,13 +180,11 @@ logsys_config_mode_set (mode); \ logsys_config_file_set (&error_string, (file)); \ logsys_config_facility_set (name, (facility)); \ @@ -6207,7 +7128,7 @@ diff -Naurd corosync-0.92/include/corosync/engine/logsys.h corosync-trunk/includ #define LOGSYS_DECLARE_NOSUBSYS(priority) \ __attribute__ ((constructor)) static void logsys_nosubsys_init (void) \ { \ -@@ -206,161 +207,88 @@ +@@ -206,161 +213,88 @@ _logsys_subsys_create ((subsys), (priority)); \ } @@ -6638,8 +7559,15 @@ diff -Naurd corosync-0.92/include/corosync/evs.h corosync-trunk/include/corosync unsigned int *member_list, diff -Naurd corosync-0.92/include/corosync/ipc_cfg.h corosync-trunk/include/corosync/ipc_cfg.h --- corosync-0.92/include/corosync/ipc_cfg.h 2008-08-15 08:15:26.000000000 +0200 -+++ corosync-trunk/include/corosync/ipc_cfg.h 2008-11-06 22:49:07.000000000 +0100 -@@ -35,8 +35,8 @@ ++++ corosync-trunk/include/corosync/ipc_cfg.h 2009-01-19 09:31:21.000000000 +0100 +@@ -1,5 +1,6 @@ + /* + * Copyright (c) 2005 MontaVista Software, Inc. ++ * Copyright (c) 2009 Red Hat, Inc. + * + * All rights reserved. + * +@@ -35,8 +36,8 @@ #define AIS_IPC_CFG_H_DEFINED #include @@ -6649,7 +7577,7 @@ diff -Naurd corosync-0.92/include/corosync/ipc_cfg.h corosync-trunk/include/coro #include "cfg.h" enum req_lib_cfg_types { -@@ -47,7 +47,10 @@ +@@ -47,7 +48,11 @@ MESSAGE_REQ_CFG_ADMINISTRATIVESTATESET = 4, MESSAGE_REQ_CFG_ADMINISTRATIVESTATEGET = 5, MESSAGE_REQ_CFG_SERVICELOAD = 6, @@ -6657,11 +7585,12 @@ diff -Naurd corosync-0.92/include/corosync/ipc_cfg.h corosync-trunk/include/coro + MESSAGE_REQ_CFG_SERVICEUNLOAD = 7, + MESSAGE_REQ_CFG_KILLNODE = 8, + MESSAGE_REQ_CFG_TRYSHUTDOWN = 9, -+ MESSAGE_REQ_CFG_REPLYTOSHUTDOWN = 10 ++ MESSAGE_REQ_CFG_REPLYTOSHUTDOWN = 10, ++ MESSAGE_REQ_CFG_GET_NODE_ADDRS = 11 }; enum res_lib_cfg_types { -@@ -58,12 +61,15 @@ +@@ -58,13 +63,17 @@ MESSAGE_RES_CFG_ADMINISTRATIVESTATESET = 4, MESSAGE_RES_CFG_ADMINISTRATIVESTATEGET = 5, MESSAGE_RES_CFG_SERVICELOAD = 6, @@ -6669,35 +7598,64 @@ diff -Naurd corosync-0.92/include/corosync/ipc_cfg.h corosync-trunk/include/coro + MESSAGE_RES_CFG_SERVICEUNLOAD = 7, + MESSAGE_RES_CFG_KILLNODE = 8, + MESSAGE_RES_CFG_TRYSHUTDOWN = 9, -+ MESSAGE_RES_CFG_TESTSHUTDOWN = 10 ++ MESSAGE_RES_CFG_TESTSHUTDOWN = 10, ++ MESSAGE_RES_CFG_GET_NODE_ADDRS = 11 }; struct req_lib_cfg_statetrack { mar_req_header_t header; - SaUint8T trackFlags; -+ uint8_t trackFlags; - CorosyncCfgStateNotificationT *notificationBufferAddress; +- CorosyncCfgStateNotificationT *notificationBufferAddress; ++ uint8_t track_flags; ++ corosync_cfg_state_notification_t *notification_buffer_address; }; -@@ -81,7 +87,7 @@ + struct res_lib_cfg_statetrack { +@@ -81,9 +90,9 @@ struct req_lib_cfg_administrativestateset { mar_req_header_t header; - SaNameT compName; -+ cs_name_t compName; - CorosyncCfgAdministrativeTargetT administrativeTarget; - CorosyncCfgAdministrativeStateT administrativeState; +- CorosyncCfgAdministrativeTargetT administrativeTarget; +- CorosyncCfgAdministrativeStateT administrativeState; ++ cs_name_t comp_name; ++ corosync_cfg_administrative_target_t administrative_target; ++ corosync_cfg_administrative_state_t administrative_state; }; -@@ -92,7 +98,7 @@ + + struct res_lib_cfg_administrativestateset { +@@ -92,9 +101,9 @@ struct req_lib_cfg_administrativestateget { mar_req_header_t header; - SaNameT compName; -+ cs_name_t compName; - CorosyncCfgAdministrativeTargetT administrativeTarget; - CorosyncCfgAdministrativeStateT administrativeState; +- CorosyncCfgAdministrativeTargetT administrativeTarget; +- CorosyncCfgAdministrativeStateT administrativeState; ++ cs_name_t comp_name; ++ corosync_cfg_administrative_target_t administrative_target; ++ corosync_cfg_administrative_state_t administrative_state; }; -@@ -140,6 +146,35 @@ + + struct res_lib_cfg_administrativestateget { +@@ -122,7 +131,7 @@ + + struct req_lib_cfg_serviceload { + mar_res_header_t header __attribute__((aligned(8))); +- char *service_name[256] __attribute__((aligned(8))); ++ char service_name[256] __attribute__((aligned(8))); + unsigned int service_ver; + }; + +@@ -132,7 +141,7 @@ + + struct req_lib_cfg_serviceunload { + mar_res_header_t header __attribute__((aligned(8))); +- char *service_name[256] __attribute__((aligned(8))); ++ char service_name[256] __attribute__((aligned(8))); + unsigned int service_ver; + }; + +@@ -140,17 +149,65 @@ mar_res_header_t header __attribute__((aligned(8))); }; @@ -6729,21 +7687,41 @@ diff -Naurd corosync-0.92/include/corosync/ipc_cfg.h corosync-trunk/include/coro + mar_res_header_t header __attribute__((aligned(8))); + unsigned int flags; +}; ++ ++struct req_lib_cfg_get_node_addrs { ++ mar_req_header_t header __attribute__((aligned(8))); ++ unsigned int nodeid; ++}; ++ ++struct res_lib_cfg_get_node_addrs { ++ mar_res_header_t header __attribute__((aligned(8))); ++ unsigned int family; ++ unsigned int num_addrs; ++ char addrs[TOTEMIP_ADDRLEN][0]; ++}; + typedef enum { AIS_AMF_ADMINISTRATIVETARGET_SERVICEUNIT = 0, AIS_AMF_ADMINISTRATIVETARGET_SERVICEGROUP = 1, -@@ -153,4 +188,11 @@ - AIS_AMF_ADMINISTRATIVESTATE_STOPPING = 2 - } corosyncAdministrativeState; + AIS_AMF_ADMINISTRATIVETARGET_COMPONENTSERVICEINSTANCE = 2, + AIS_AMF_ADMINISTRATIVETARGET_NODE = 3 +-} corosyncAdministrativeTarget; ++} corosync_administrative_target_t; + typedef enum { + AIS_AMF_ADMINISTRATIVESTATE_UNLOCKED = 0, + AIS_AMF_ADMINISTRATIVESTATE_LOCKED = 1, + AIS_AMF_ADMINISTRATIVESTATE_STOPPING = 2 +-} corosyncAdministrativeState; ++} corosync_administrative_state_t; ++ +typedef enum { + CFG_SHUTDOWN_FLAG_REQUEST = 0, + CFG_SHUTDOWN_FLAG_REGARDLESS = 1, + CFG_SHUTDOWN_FLAG_IMMEDIATE = 2, -+} CorosyncShutdownFlagsT; -+ ++} corosync_shutdown_flags_t; + + #endif /* AIS_IPC_CFG_H_DEFINED */ diff -Naurd corosync-0.92/include/corosync/ipc_confdb.h corosync-trunk/include/corosync/ipc_confdb.h --- corosync-0.92/include/corosync/ipc_confdb.h 2008-09-03 09:58:08.000000000 +0200 @@ -6759,7 +7737,7 @@ diff -Naurd corosync-0.92/include/corosync/ipc_confdb.h corosync-trunk/include/c enum req_confdb_types { diff -Naurd corosync-0.92/include/corosync/ipc_cpg.h corosync-trunk/include/corosync/ipc_cpg.h --- corosync-0.92/include/corosync/ipc_cpg.h 2008-09-17 21:15:00.000000000 +0200 -+++ corosync-trunk/include/corosync/ipc_cpg.h 2008-11-06 22:49:07.000000000 +0100 ++++ corosync-trunk/include/corosync/ipc_cpg.h 2009-01-08 07:29:16.000000000 +0100 @@ -35,7 +35,7 @@ #define IPC_CPG_H_DEFINED @@ -6769,6 +7747,15 @@ diff -Naurd corosync-0.92/include/corosync/ipc_cpg.h corosync-trunk/include/coro #include "ipc_gen.h" #include "mar_cpg.h" +@@ -143,7 +143,7 @@ + + struct req_lib_cpg_membership { + mar_req_header_t header __attribute__((aligned(8))); +- mar_cpg_name_t group_name __attribute__((aligned(8))); ++// mar_cpg_name_t group_name __attribute__((aligned(8))); + }; + + struct res_lib_cpg_confchg_callback { diff -Naurd corosync-0.92/include/corosync/ipc_evs.h corosync-trunk/include/corosync/ipc_evs.h --- corosync-0.92/include/corosync/ipc_evs.h 2008-08-14 16:59:50.000000000 +0200 +++ corosync-trunk/include/corosync/ipc_evs.h 2008-11-06 22:49:07.000000000 +0100 @@ -6957,6 +7944,159 @@ diff -Naurd corosync-0.92/include/corosync/ipc_quorum.h corosync-trunk/include/c +}; + +#endif +diff -Naurd corosync-0.92/include/corosync/ipc_votequorum.h corosync-trunk/include/corosync/ipc_votequorum.h +--- corosync-0.92/include/corosync/ipc_votequorum.h 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/include/corosync/ipc_votequorum.h 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,149 @@ ++/* ++ * Copyright (c) 2009 Red Hat, Inc. ++ * ++ * All rights reserved. ++ * ++ * Author: Christine Caulfield (ccaulfie@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 CONTIBUTORS "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 IPC_VOTEQUORUM_H_DEFINED ++#define IPC_VOTEQUORUM_H_DEFINED ++ ++#include "corosync/corotypes.h" ++#include "corosync/ipc_gen.h" ++ ++// ILLEGAL value!! ++#define VOTEQUORUM_SERVICE 15 ++ ++#define VOTEQUORUM_MAX_QDISK_NAME_LEN 255 ++ ++ ++enum req_votequorum_types { ++ MESSAGE_REQ_VOTEQUORUM_GETINFO = 0, ++ MESSAGE_REQ_VOTEQUORUM_SETEXPECTED, ++ MESSAGE_REQ_VOTEQUORUM_SETVOTES, ++ MESSAGE_REQ_VOTEQUORUM_QDISK_REGISTER, ++ MESSAGE_REQ_VOTEQUORUM_QDISK_UNREGISTER, ++ MESSAGE_REQ_VOTEQUORUM_QDISK_POLL, ++ MESSAGE_REQ_VOTEQUORUM_QDISK_GETINFO, ++ MESSAGE_REQ_VOTEQUORUM_SETSTATE, ++ MESSAGE_REQ_VOTEQUORUM_LEAVING, ++ MESSAGE_REQ_VOTEQUORUM_TRACKSTART, ++ MESSAGE_REQ_VOTEQUORUM_TRACKSTOP ++}; ++ ++enum res_votequorum_types { ++ MESSAGE_RES_VOTEQUORUM_STATUS = 0, ++ MESSAGE_RES_VOTEQUORUM_GETINFO, ++ MESSAGE_RES_VOTEQUORUM_QDISK_GETINFO, ++ MESSAGE_RES_VOTEQUORUM_TRACKSTART, ++ MESSAGE_RES_VOTEQUORUM_NOTIFICATION ++}; ++ ++struct req_lib_votequorum_setvotes { ++ mar_req_header_t header __attribute__((aligned(8))); ++ unsigned int votes; ++ int nodeid; ++}; ++ ++struct req_lib_votequorum_qdisk_register { ++ mar_req_header_t header __attribute__((aligned(8))); ++ unsigned int votes; ++ char name[VOTEQUORUM_MAX_QDISK_NAME_LEN]; ++}; ++ ++struct req_lib_votequorum_qdisk_poll { ++ mar_req_header_t header __attribute__((aligned(8))); ++ int state; ++}; ++ ++struct req_lib_votequorum_setexpected { ++ mar_req_header_t header __attribute__((aligned(8))); ++ unsigned int expected_votes; ++}; ++ ++struct req_lib_votequorum_trackstart { ++ mar_req_header_t header __attribute__((aligned(8))); ++ uint64_t context; ++ unsigned int track_flags; ++}; ++ ++struct req_lib_votequorum_general { ++ mar_req_header_t header __attribute__((aligned(8))); ++}; ++ ++#define VOTEQUORUM_REASON_KILL_REJECTED 1 ++#define VOTEQUORUM_REASON_KILL_APPLICATION 2 ++#define VOTEQUORUM_REASON_KILL_REJOIN 3 ++ ++struct req_lib_votequorum_getinfo { ++ mar_req_header_t header __attribute__((aligned(8))); ++ int nodeid; ++}; ++ ++struct res_lib_votequorum_status { ++ mar_res_header_t header __attribute__((aligned(8))); ++}; ++ ++#define VOTEQUORUM_INFO_FLAG_HASSTATE 1 ++#define VOTEQUORUM_INFO_FLAG_DISALLOWED 2 ++#define VOTEQUORUM_INFO_FLAG_TWONODE 4 ++#define VOTEQUORUM_INFO_FLAG_QUORATE 8 ++ ++struct res_lib_votequorum_getinfo { ++ mar_res_header_t header __attribute__((aligned(8))); ++ int nodeid; ++ unsigned int votes; ++ unsigned int expected_votes; ++ unsigned int highest_expected; ++ unsigned int total_votes; ++ unsigned int quorum; ++ unsigned int flags; ++}; ++ ++struct res_lib_votequorum_qdisk_getinfo { ++ mar_res_header_t header __attribute__((aligned(8))); ++ unsigned int votes; ++ unsigned int state; ++ char name[VOTEQUORUM_MAX_QDISK_NAME_LEN]; ++}; ++ ++struct votequorum_node { ++ mar_uint32_t nodeid; ++ mar_uint32_t state; ++}; ++ ++struct res_lib_votequorum_notification { ++ mar_res_header_t header __attribute__((aligned(8))); ++ mar_uint32_t quorate __attribute__((aligned(8))); ++ mar_uint64_t context __attribute__((aligned(8))); ++ mar_uint32_t node_list_entries __attribute__((aligned(8))); ++ struct votequorum_node node_list[] __attribute__((aligned(8))); ++}; ++ ++#endif diff -Naurd corosync-0.92/include/corosync/mar_gen.h corosync-trunk/include/corosync/mar_gen.h --- corosync-0.92/include/corosync/mar_gen.h 2008-08-15 08:15:26.000000000 +0200 +++ corosync-trunk/include/corosync/mar_gen.h 2008-11-06 22:49:07.000000000 +0100 @@ -7442,6 +8582,18 @@ diff -Naurd corosync-0.92/include/corosync/totem/totem.h corosync-trunk/include/ enum totem_callback_token_type { TOTEM_CALLBACK_TOKEN_RECEIVED = 1, TOTEM_CALLBACK_TOKEN_SENT = 2 +diff -Naurd corosync-0.92/include/corosync/totem/totemip.h corosync-trunk/include/corosync/totem/totemip.h +--- corosync-0.92/include/corosync/totem/totemip.h 2008-08-14 16:59:50.000000000 +0200 ++++ corosync-trunk/include/corosync/totem/totemip.h 2009-01-25 22:15:25.000000000 +0100 +@@ -72,7 +72,7 @@ + extern int totemip_totemip_to_sockaddr_convert(struct totem_ip_address *ip_addr, + uint16_t port, struct sockaddr_storage *saddr, int *addrlen); + extern int totemip_parse(struct totem_ip_address *totemip, char *addr, int family); +-extern int totemip_iface_check(struct totem_ip_address *bindnet, struct totem_ip_address *boundto, int *interface_up, int *interface_num); ++extern int totemip_iface_check(struct totem_ip_address *bindnet, struct totem_ip_address *boundto, int *interface_up, int *interface_num, int mask_high_bit); + + /* These two simulate a zero in_addr by clearing the family field */ + static inline void totemip_zero_set(struct totem_ip_address *addr) diff -Naurd corosync-0.92/include/corosync/totem/totempg.h corosync-trunk/include/corosync/totem/totempg.h --- corosync-0.92/include/corosync/totem/totempg.h 2008-08-14 16:59:50.000000000 +0200 +++ corosync-trunk/include/corosync/totem/totempg.h 2008-12-01 19:44:55.000000000 +0100 @@ -7454,6 +8606,208 @@ diff -Naurd corosync-0.92/include/corosync/totem/totempg.h corosync-trunk/includ extern int totempg_my_family_get (void); +diff -Naurd corosync-0.92/include/corosync/votequorum.h corosync-trunk/include/corosync/votequorum.h +--- corosync-0.92/include/corosync/votequorum.h 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/include/corosync/votequorum.h 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,198 @@ ++/* ++ * Copyright (c) 2009 Red Hat, Inc. ++ * ++ * All rights reserved. ++ * ++ * Author: Christine Caulfield (ccaulfie@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 CONTIBUTORS "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 COROSYNC_VOTEQUORUM_H_DEFINED ++#define COROSYNC_VOTEQUORUM_H_DEFINED ++ ++typedef uint64_t votequorum_handle_t; ++ ++ ++#define VOTEQUORUM_MAX_QDISK_NAME_LEN 255 ++ ++#define VOTEQUORUM_INFO_FLAG_HASSTATE 1 ++#define VOTEQUORUM_INFO_FLAG_DISALLOWED 2 ++#define VOTEQUORUM_INFO_FLAG_TWONODE 4 ++#define VOTEQUORUM_INFO_FLAG_QUORATE 8 ++ ++#define NODESTATE_JOINING 1 ++#define NODESTATE_MEMBER 2 ++#define NODESTATE_DEAD 3 ++#define NODESTATE_LEAVING 4 ++#define NODESTATE_DISALLOWED 5 ++ ++ ++/** @} */ ++ ++struct votequorum_info { ++ unsigned int node_id; ++ unsigned int node_votes; ++ unsigned int node_expected_votes; ++ unsigned int highest_expected; ++ unsigned int total_votes; ++ unsigned int quorum; ++ unsigned int flags; ++}; ++ ++struct votequorum_qdisk_info { ++ unsigned int votes; ++ unsigned int state; ++ char name[VOTEQUORUM_MAX_QDISK_NAME_LEN]; ++}; ++ ++typedef struct { ++ uint32_t nodeid; ++ uint32_t state; ++} votequorum_node_t; ++ ++ ++typedef void (*votequorum_notification_fn_t) ( ++ votequorum_handle_t handle, ++ uint64_t context, ++ uint32_t quorate, ++ uint32_t node_list_entries, ++ votequorum_node_t node_list[] ++ ); ++ ++typedef struct { ++ votequorum_notification_fn_t votequorum_notify_fn; ++} votequorum_callbacks_t; ++ ++ ++/* ++ * Create a new quorum connection ++ */ ++cs_error_t votequorum_initialize ( ++ votequorum_handle_t *handle, ++ votequorum_callbacks_t *callbacks); ++ ++/* ++ * Close the quorum handle ++ */ ++cs_error_t votequorum_finalize ( ++ votequorum_handle_t handle); ++ ++ ++/* ++ * Dispatch messages and configuration changes ++ */ ++cs_error_t votequorum_dispatch ( ++ votequorum_handle_t handle, ++ cs_dispatch_flags_t dispatch_types); ++ ++ ++/* ++ * Get quorum information. ++ */ ++cs_error_t votequorum_getinfo ( ++ votequorum_handle_t handle, ++ unsigned int nodeid, ++ struct votequorum_info *info); ++ ++/* ++ * set expected_votes ++ */ ++cs_error_t votequorum_setexpected ( ++ votequorum_handle_t handle, ++ unsigned int expected_votes); ++ ++/* ++ * set votes for a node ++ */ ++cs_error_t votequorum_setvotes ( ++ votequorum_handle_t handle, ++ unsigned int nodeid, ++ unsigned int votes); ++ ++/* ++ * Register a quorum device ++ * it will be DEAD until polled ++ */ ++cs_error_t votequorum_qdisk_register ( ++ votequorum_handle_t handle, ++ char *name, ++ unsigned int votes); ++ ++/* ++ * Unregister a quorum device ++ */ ++cs_error_t votequorum_qdisk_unregister ( ++ votequorum_handle_t handle); ++ ++/* ++ * Poll a quorum device ++ */ ++cs_error_t votequorum_qdisk_poll ( ++ votequorum_handle_t handle, ++ unsigned int state); ++ ++/* ++ * Get quorum device information ++ */ ++cs_error_t votequorum_qdisk_getinfo ( ++ votequorum_handle_t handle, ++ struct votequorum_qdisk_info *info); ++ ++/* ++ * Set the "hasstate" bit for this node ++ */ ++cs_error_t votequorum_setstate ( ++ votequorum_handle_t handle); ++ ++/* Track node and quorum changes */ ++cs_error_t votequorum_trackstart ( ++ votequorum_handle_t handle, ++ uint64_t context, ++ unsigned int flags ); ++ ++cs_error_t votequorum_trackstop ( ++ votequorum_handle_t handle); ++ ++/* ++ * Set our LEAVING flag. we should exit soon after this ++ */ ++cs_error_t votequorum_leaving ( ++ votequorum_handle_t handle); ++ ++/* ++ * Save and retrieve private data/context ++ */ ++cs_error_t votequorum_context_get ( ++ votequorum_handle_t handle, ++ void **context); ++ ++cs_error_t votequorum_context_set ( ++ votequorum_handle_t handle, ++ void *context); ++ ++#endif /* COROSYNC_VOTEQUORUM_H_DEFINED */ diff -Naurd corosync-0.92/lcr/Makefile corosync-trunk/lcr/Makefile --- corosync-0.92/lcr/Makefile 2008-08-15 08:15:26.000000000 +0200 +++ corosync-trunk/lcr/Makefile 2008-11-11 18:26:58.000000000 +0100 @@ -7532,8 +8886,15 @@ diff -Naurd corosync-0.92/lcr/uis.c corosync-trunk/lcr/uis.c diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c --- corosync-0.92/lib/cfg.c 2008-08-15 08:15:26.000000000 +0200 -+++ corosync-trunk/lib/cfg.c 2008-11-11 18:26:58.000000000 +0100 -@@ -7,7 +7,7 @@ ++++ corosync-trunk/lib/cfg.c 2009-01-19 09:31:21.000000000 +0100 +@@ -1,13 +1,13 @@ + /* + * Copyright (c) 2002-2005 MontaVista Software, Inc. +- * Copyright (c) 2006-2007 Red Hat, 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: @@ -7542,13 +8903,20 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * -@@ -45,14 +45,14 @@ +@@ -40,19 +40,21 @@ + #include + #include + #include ++#include + #include + #include #include #include -#include +#include #include ++#include #include #include #include @@ -7559,16 +8927,43 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c mar_res_header_t header; char data[4096]; }; -@@ -64,7 +64,7 @@ +@@ -63,15 +65,15 @@ + struct cfg_instance { int response_fd; int dispatch_fd; - CorosyncCfgCallbacksT callbacks; +- CorosyncCfgCallbacksT callbacks; - SaNameT compName; -+ cs_name_t compName; - int compRegistered; +- int compRegistered; ++ corosync_cfg_callbacks_t callbacks; ++ cs_name_t comp_name; ++ int comp_registered; int finalize; pthread_mutex_t response_mutex; -@@ -94,31 +94,31 @@ + pthread_mutex_t dispatch_mutex; + }; + +-static void cfg_handleInstanceDestructor (void *); ++static void cfg_handle_instance_destructor (void *); + + /* + * All instances in one database +@@ -80,13 +82,13 @@ + .handleCount = 0, + .handles = 0, + .mutex = PTHREAD_MUTEX_INITIALIZER, +- .handleInstanceDestructor = cfg_handleInstanceDestructor ++ .handleInstanceDestructor = cfg_handle_instance_destructor + }; + + /* + * Implementation + */ +-void cfg_handleInstanceDestructor (void *instance) ++void cfg_handle_instance_destructor (void *instance) + { + struct cfg_instance *cfg_instance = instance; + +@@ -94,84 +96,85 @@ pthread_mutex_destroy (&cfg_instance->dispatch_mutex); } @@ -7576,7 +8971,8 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c +cs_error_t corosync_cfg_initialize ( corosync_cfg_handle_t *cfg_handle, - const CorosyncCfgCallbacksT *cfgCallbacks) +- const CorosyncCfgCallbacksT *cfgCallbacks) ++ const corosync_cfg_callbacks_t *cfg_callbacks) { struct cfg_instance *cfg_instance; - SaAisErrorT error = SA_AIS_OK; @@ -7606,7 +9002,13 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c goto error_put_destroy; } -@@ -130,48 +130,49 @@ +- if (cfgCallbacks) { +- memcpy (&cfg_instance->callbacks, cfgCallbacks, sizeof (CorosyncCfgCallbacksT)); ++ if (cfg_callbacks) { ++ memcpy (&cfg_instance->callbacks, cfg_callbacks, sizeof (corosync_cfg_callbacks_t)); + } + + pthread_mutex_init (&cfg_instance->response_mutex, NULL); pthread_mutex_init (&cfg_instance->dispatch_mutex, NULL); @@ -7657,7 +9059,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c corosync_cfg_dispatch ( corosync_cfg_handle_t cfg_handle, - SaDispatchFlagsT dispatchFlags) -+ cs_dispatch_flags_t dispatchFlags) ++ cs_dispatch_flags_t dispatch_flags) { struct pollfd ufds; int timeout = -1; @@ -7670,11 +9072,13 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c #ifdef COMPILE_OUT struct res_lib_corosync_healthcheckcallback *res_lib_corosync_healthcheckcallback; struct res_lib_corosync_readinessstatesetcallback *res_lib_corosync_readinessstatesetcallback; -@@ -180,18 +181,18 @@ +@@ -179,19 +182,19 @@ + struct res_lib_corosync_csiremovecallback *res_lib_corosync_csiremovecallback; struct res_lib_cfg_statetrackcallback *res_lib_cfg_statetrackcallback; #endif - CorosyncCfgCallbacksT callbacks; +- CorosyncCfgCallbacksT callbacks; - struct res_overlay dispatch_data; ++ corosync_cfg_callbacks_t callbacks; + struct cfg_res_overlay dispatch_data; error = saHandleInstanceGet (&cfg_hdb, cfg_handle, @@ -7689,11 +9093,11 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c + * Timeout instantly for CS_DISPATCH_ALL */ - if (dispatchFlags == SA_DISPATCH_ALL) { -+ if (dispatchFlags == CS_DISPATCH_ALL) { ++ if (dispatch_flags == CS_DISPATCH_ALL) { timeout = 0; } -@@ -204,14 +205,14 @@ +@@ -204,14 +207,14 @@ ufds.revents = 0; error = saPollRetry (&ufds, 1, timeout); @@ -7710,7 +9114,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c goto error_nounlock; } -@@ -219,13 +220,13 @@ +@@ -219,13 +222,13 @@ * Handle has been finalized in another thread */ if (cfg_instance->finalize == 1) { @@ -7722,11 +9126,11 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c dispatch_avail = ufds.revents & POLLIN; - if (dispatch_avail == 0 && dispatchFlags == SA_DISPATCH_ALL) { -+ if (dispatch_avail == 0 && dispatchFlags == CS_DISPATCH_ALL) { ++ if (dispatch_avail == 0 && dispatch_flags == CS_DISPATCH_ALL) { pthread_mutex_unlock (&cfg_instance->dispatch_mutex); break; /* exit do while cont is 1 loop */ } else -@@ -240,13 +241,13 @@ +@@ -240,13 +243,13 @@ */ error = saRecvRetry (cfg_instance->dispatch_fd, &dispatch_data.header, sizeof (mar_res_header_t)); @@ -7742,15 +9146,23 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c goto error_unlock; } } -@@ -267,9 +268,14 @@ +@@ -260,16 +263,21 @@ + * A risk of this dispatch method is that the callback routines may + * operate at the same time that cfgFinalize has been called in another thread. + */ +- memcpy (&callbacks, &cfg_instance->callbacks, sizeof (CorosyncCfgCallbacksT)); ++ memcpy (&callbacks, &cfg_instance->callbacks, sizeof (corosync_cfg_callbacks_t)); + pthread_mutex_unlock (&cfg_instance->dispatch_mutex); + + /* * Dispatch incoming response */ switch (dispatch_data.header.id) { - + case MESSAGE_RES_CFG_TESTSHUTDOWN: -+ if (callbacks.corosyncCfgShutdownCallback) { ++ if (callbacks.corosync_cfg_shutdown_callback) { + res_lib_cfg_testshutdown = (struct res_lib_cfg_testshutdown *)&dispatch_data; -+ callbacks.corosyncCfgShutdownCallback(cfg_handle, res_lib_cfg_testshutdown->flags); ++ callbacks.corosync_cfg_shutdown_callback(cfg_handle, res_lib_cfg_testshutdown->flags); + } + break; default: @@ -7759,11 +9171,13 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c goto error_nounlock; break; } -@@ -278,31 +284,31 @@ +@@ -277,32 +285,32 @@ + /* * Determine if more messages should be processed */ - switch (dispatchFlags) { +- switch (dispatchFlags) { - case SA_DISPATCH_ONE: ++ switch (dispatch_flags) { + case CS_DISPATCH_ONE: cont = 0; break; @@ -7798,7 +9212,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c return (error); } -@@ -316,8 +322,8 @@ +@@ -316,8 +324,8 @@ if (cfg_instance->finalize) { pthread_mutex_unlock (&cfg_instance->response_mutex); pthread_mutex_unlock (&cfg_instance->dispatch_mutex); @@ -7809,7 +9223,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c } cfg_instance->finalize = 1; -@@ -330,7 +336,7 @@ +@@ -330,7 +338,7 @@ pthread_mutex_destroy (&cfg_instance->dispatch_mutex); @@ -7818,7 +9232,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c if (cfg_instance->response_fd != -1) { shutdown (cfg_instance->response_fd, 0); -@@ -341,12 +347,12 @@ +@@ -341,12 +349,12 @@ close (cfg_instance->dispatch_fd); } @@ -7833,7 +9247,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c corosync_cfg_ring_status_get ( corosync_cfg_handle_t cfg_handle, char ***interface_names, -@@ -357,10 +363,10 @@ +@@ -357,10 +365,10 @@ struct req_lib_cfg_ringstatusget req_lib_cfg_ringstatusget; struct res_lib_cfg_ringstatusget res_lib_cfg_ringstatusget; unsigned int i; @@ -7846,7 +9260,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c return (error); } -@@ -380,13 +386,13 @@ +@@ -380,13 +388,13 @@ *interface_count = res_lib_cfg_ringstatusget.interface_count; *interface_names = malloc (sizeof (char *) * *interface_count); if (*interface_names == NULL) { @@ -7862,7 +9276,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c goto error_free_interface_names; } memset (*status, 0, sizeof (char *) * *interface_count); -@@ -394,12 +400,12 @@ +@@ -394,12 +402,12 @@ for (i = 0; i < res_lib_cfg_ringstatusget.interface_count; i++) { (*(interface_names))[i] = strdup (res_lib_cfg_ringstatusget.interface_name[i]); if ((*(interface_names))[i] == NULL) { @@ -7877,7 +9291,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c goto error_free_contents; } } -@@ -416,27 +422,27 @@ +@@ -416,27 +424,27 @@ } free (*status); @@ -7911,7 +9325,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c return (error); } -@@ -452,12 +458,12 @@ +@@ -452,12 +460,12 @@ sizeof (struct res_lib_cfg_ringreenable)); pthread_mutex_unlock (&cfg_instance->response_mutex); @@ -7926,7 +9340,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c corosync_cfg_service_load ( corosync_cfg_handle_t cfg_handle, char *service_name, -@@ -466,10 +472,10 @@ +@@ -466,10 +474,10 @@ struct cfg_instance *cfg_instance; struct req_lib_cfg_serviceload req_lib_cfg_serviceload; struct res_lib_cfg_serviceload res_lib_cfg_serviceload; @@ -7939,7 +9353,16 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c return (error); } -@@ -490,12 +496,12 @@ +@@ -477,7 +485,7 @@ + req_lib_cfg_serviceload.header.id = MESSAGE_REQ_CFG_SERVICELOAD; + memset (&req_lib_cfg_serviceload.service_name, 0, + sizeof (req_lib_cfg_serviceload.service_name)); +- strncpy ((char *)req_lib_cfg_serviceload.service_name, service_name, ++ strncpy (req_lib_cfg_serviceload.service_name, service_name, + sizeof (req_lib_cfg_serviceload.service_name) - 1); + req_lib_cfg_serviceload.service_ver = service_ver; + +@@ -490,12 +498,12 @@ sizeof (struct res_lib_cfg_serviceload)); pthread_mutex_unlock (&cfg_instance->response_mutex); @@ -7954,7 +9377,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c corosync_cfg_service_unload ( corosync_cfg_handle_t cfg_handle, char *service_name, -@@ -504,10 +510,10 @@ +@@ -504,10 +512,10 @@ struct cfg_instance *cfg_instance; struct req_lib_cfg_serviceunload req_lib_cfg_serviceunload; struct res_lib_cfg_serviceunload res_lib_cfg_serviceunload; @@ -7967,7 +9390,16 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c return (error); } -@@ -528,20 +534,20 @@ +@@ -515,7 +523,7 @@ + req_lib_cfg_serviceunload.header.id = MESSAGE_REQ_CFG_SERVICEUNLOAD; + memset (&req_lib_cfg_serviceunload.service_name, 0, + sizeof (req_lib_cfg_serviceunload.service_name)); +- strncpy ((char *)req_lib_cfg_serviceunload.service_name, service_name, ++ strncpy (req_lib_cfg_serviceunload.service_name, service_name, + sizeof (req_lib_cfg_serviceunload.service_name) - 1); + req_lib_cfg_serviceunload.service_ver = service_ver; + +@@ -528,29 +536,29 @@ sizeof (struct res_lib_cfg_serviceunload)); pthread_mutex_unlock (&cfg_instance->response_mutex); @@ -7981,8 +9413,9 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c corosync_cfg_state_track ( corosync_cfg_handle_t cfg_handle, - SaUint8T trackFlags, -+ uint8_t trackFlags, - const CorosyncCfgStateNotificationT *notificationBuffer) +- const CorosyncCfgStateNotificationT *notificationBuffer) ++ uint8_t track_flags, ++ const corosync_cfg_state_notification_t *notification_buffer) { struct cfg_instance *cfg_instance; struct req_lib_cfg_statetrack req_lib_cfg_statetrack; @@ -7992,7 +9425,10 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c req_lib_cfg_statetrack.header.size = sizeof (struct req_lib_cfg_statetrack); req_lib_cfg_statetrack.header.id = MESSAGE_REQ_CFG_STATETRACKSTART; -@@ -550,7 +556,7 @@ +- req_lib_cfg_statetrack.trackFlags = trackFlags; +- req_lib_cfg_statetrack.notificationBufferAddress = (CorosyncCfgStateNotificationT *)notificationBuffer; ++ req_lib_cfg_statetrack.track_flags = track_flags; ++ req_lib_cfg_statetrack.notification_buffer_address = (corosync_cfg_state_notification_t *)notification_buffer; error = saHandleInstanceGet (&cfg_hdb, cfg_handle, (void *)&cfg_instance); @@ -8001,7 +9437,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c return (error); } -@@ -564,23 +570,23 @@ +@@ -564,23 +572,23 @@ pthread_mutex_unlock (&cfg_instance->response_mutex); @@ -8030,7 +9466,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c return (error); } -@@ -597,12 +603,12 @@ +@@ -597,31 +605,33 @@ pthread_mutex_unlock (&cfg_instance->response_mutex); @@ -8045,8 +9481,11 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c +cs_error_t corosync_cfg_admin_state_get ( corosync_cfg_handle_t cfg_handle, - CorosyncCfgAdministrativeTargetT administrativeTarget, -@@ -611,11 +617,11 @@ +- CorosyncCfgAdministrativeTargetT administrativeTarget, +- CorosyncCfgAdministrativeStateT *administrativeState) ++ corosync_cfg_administrative_target_t administrative_target, ++ corosync_cfg_administrative_state_t *administrative_state) + { struct cfg_instance *cfg_instance; struct req_lib_cfg_administrativestateget req_lib_cfg_administrativestateget; struct res_lib_cfg_administrativestateget res_lib_cfg_administrativestateget; @@ -8060,7 +9499,16 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c return (error); } -@@ -633,12 +639,12 @@ + req_lib_cfg_administrativestateget.header.id = MESSAGE_REQ_CFG_ADMINISTRATIVESTATEGET; + req_lib_cfg_administrativestateget.header.size = sizeof (struct req_lib_cfg_administrativestateget); +- req_lib_cfg_administrativestateget.administrativeTarget = administrativeTarget; ++ req_lib_cfg_administrativestateget.administrative_target = administrative_target; ++ ++ pthread_mutex_lock (&cfg_instance->response_mutex); + + error = saSendReceiveReply (cfg_instance->response_fd, + &req_lib_cfg_administrativestateget, +@@ -633,32 +643,34 @@ pthread_mutex_unlock (&cfg_instance->response_mutex); @@ -8075,8 +9523,11 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c +cs_error_t corosync_cfg_admin_state_set ( corosync_cfg_handle_t cfg_handle, - CorosyncCfgAdministrativeTargetT administrativeTarget, -@@ -647,11 +653,11 @@ +- CorosyncCfgAdministrativeTargetT administrativeTarget, +- CorosyncCfgAdministrativeStateT administrativeState) ++ corosync_cfg_administrative_target_t administrative_target, ++ corosync_cfg_administrative_state_t administrative_state) + { struct cfg_instance *cfg_instance; struct req_lib_cfg_administrativestateset req_lib_cfg_administrativestateset; struct res_lib_cfg_administrativestateset res_lib_cfg_administrativestateset; @@ -8090,7 +9541,18 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c return (error); } -@@ -670,7 +676,109 @@ + req_lib_cfg_administrativestateset.header.id = MESSAGE_REQ_CFG_ADMINISTRATIVESTATEGET; + req_lib_cfg_administrativestateset.header.size = sizeof (struct req_lib_cfg_administrativestateset); +- req_lib_cfg_administrativestateset.administrativeTarget = administrativeTarget; +- req_lib_cfg_administrativestateset.administrativeState = administrativeState; ++ req_lib_cfg_administrativestateset.administrative_target = administrative_target; ++ req_lib_cfg_administrativestateset.administrative_state = administrative_state; ++ ++ pthread_mutex_lock (&cfg_instance->response_mutex); + + error = saSendReceiveReply (cfg_instance->response_fd, + &req_lib_cfg_administrativestateset, +@@ -670,7 +682,191 @@ pthread_mutex_unlock (&cfg_instance->response_mutex); @@ -8127,6 +9589,8 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c + strcpy((char *)req_lib_cfg_killnode.reason.value, reason); + req_lib_cfg_killnode.reason.length = strlen(reason)+1; + ++ pthread_mutex_lock (&cfg_instance->response_mutex); ++ + error = saSendReceiveReply (cfg_instance->response_fd, + &req_lib_cfg_killnode, + sizeof (struct req_lib_cfg_killnode), @@ -8145,7 +9609,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c +cs_error_t +corosync_cfg_try_shutdown ( + corosync_cfg_handle_t cfg_handle, -+ CorosyncCfgShutdownFlagsT flags) ++ corosync_cfg_shutdown_flags_t flags) +{ + struct cfg_instance *cfg_instance; + struct req_lib_cfg_tryshutdown req_lib_cfg_tryshutdown; @@ -8162,6 +9626,8 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c + req_lib_cfg_tryshutdown.header.size = sizeof (struct req_lib_cfg_tryshutdown); + req_lib_cfg_tryshutdown.flags = flags; + ++ pthread_mutex_lock (&cfg_instance->response_mutex); ++ + error = saSendReceiveReply (cfg_instance->response_fd, + &req_lib_cfg_tryshutdown, + sizeof (struct req_lib_cfg_tryshutdown), @@ -8178,7 +9644,7 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c +cs_error_t +corosync_cfg_replyto_shutdown ( + corosync_cfg_handle_t cfg_handle, -+ CorosyncCfgShutdownReplyFlagsT response) ++ corosync_cfg_shutdown_reply_flags_t response) +{ + struct cfg_instance *cfg_instance; + struct req_lib_cfg_replytoshutdown req_lib_cfg_replytoshutdown; @@ -8197,14 +9663,99 @@ diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c + + iov.iov_base = &req_lib_cfg_replytoshutdown; + iov.iov_len = sizeof (struct req_lib_cfg_replytoshutdown); ++ ++ pthread_mutex_lock (&cfg_instance->response_mutex); + error = saSendMsgRetry (cfg_instance->response_fd, + &iov, 1); + -+ return (error); ++ pthread_mutex_unlock (&cfg_instance->response_mutex); ++ ++ return (error); ++} ++ ++cs_error_t corosync_cfg_get_node_addrs ( ++ corosync_cfg_handle_t cfg_handle, ++ int nodeid, ++ int max_addrs, ++ int *num_addrs, ++ corosync_cfg_node_address_t *addrs) ++{ ++ cs_error_t error; ++ char buf[PIPE_BUF]; ++ struct req_lib_cfg_get_node_addrs req_lib_cfg_get_node_addrs; ++ struct res_lib_cfg_get_node_addrs * res_lib_cfg_get_node_addrs = (struct res_lib_cfg_get_node_addrs *)buf; ++ struct cfg_instance *cfg_instance; ++ int addrlen; ++ int i; ++ struct iovec iov[2]; ++ ++ error = saHandleInstanceGet (&cfg_hdb, cfg_handle, ++ (void *)&cfg_instance); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ pthread_mutex_lock (&cfg_instance->response_mutex); ++ ++ req_lib_cfg_get_node_addrs.header.size = sizeof (req_lib_cfg_get_node_addrs); ++ req_lib_cfg_get_node_addrs.header.id = MESSAGE_REQ_CFG_GET_NODE_ADDRS; ++ req_lib_cfg_get_node_addrs.nodeid = nodeid; ++ ++ iov[0].iov_base = (char *)&req_lib_cfg_get_node_addrs; ++ iov[0].iov_len = sizeof (req_lib_cfg_get_node_addrs); ++ ++ error = saSendMsgReceiveReply (cfg_instance->response_fd, iov, 1, ++ res_lib_cfg_get_node_addrs, sizeof (mar_res_header_t)); ++ ++ if (error == CS_OK && res_lib_cfg_get_node_addrs->header.size > sizeof(mar_res_header_t)) { ++ error = saRecvRetry (cfg_instance->response_fd, (char *)res_lib_cfg_get_node_addrs + sizeof (mar_res_header_t), ++ res_lib_cfg_get_node_addrs->header.size - sizeof (mar_res_header_t)); ++ } ++ pthread_mutex_unlock (&cfg_instance->response_mutex); ++ ++ if (error != CS_OK) { ++ goto error_exit; ++ } ++ ++ if (res_lib_cfg_get_node_addrs->family == AF_INET) ++ addrlen = sizeof(struct sockaddr_in); ++ if (res_lib_cfg_get_node_addrs->family == AF_INET6) ++ addrlen = sizeof(struct sockaddr_in6); ++ ++ for (i=0; inum_addrs; i++) { ++ addrs[i].addressLength = addrlen; ++ struct sockaddr_in *in; ++ struct sockaddr_in6 *in6; ++ ++ if (res_lib_cfg_get_node_addrs->family == AF_INET) { ++ in = (struct sockaddr_in *)addrs[i].address; ++ in->sin_family = AF_INET; ++ memcpy(&in->sin_addr, &res_lib_cfg_get_node_addrs->addrs[i][0], sizeof(struct in_addr)); ++ } ++ if (res_lib_cfg_get_node_addrs->family == AF_INET6) { ++ in6 = (struct sockaddr_in6 *)addrs[i].address; ++ in6->sin6_family = AF_INET6; ++ memcpy(&in6->sin6_addr, &res_lib_cfg_get_node_addrs->addrs[i][0], sizeof(struct in6_addr)); ++ } ++ } ++ *num_addrs = res_lib_cfg_get_node_addrs->num_addrs; ++ errno = error = res_lib_cfg_get_node_addrs->header.error; ++ ++error_exit: ++ ++ pthread_mutex_unlock (&cfg_instance->response_mutex); ++ return (error); } diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c --- corosync-0.92/lib/confdb.c 2008-09-03 09:58:08.000000000 +0200 -+++ corosync-trunk/lib/confdb.c 2008-11-11 18:26:58.000000000 +0100 ++++ corosync-trunk/lib/confdb.c 2009-01-23 16:41:06.000000000 +0100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2008 Red Hat, Inc. ++ * Copyright (c) 2008-2009 Red Hat, Inc. + * + * All rights reserved. + * @@ -42,7 +42,7 @@ #include #include @@ -8421,13 +9972,13 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c int cont = 1; /* always continue do loop except when set to 0 */ int dispatch_avail; struct confdb_inst *confdb_inst; -@@ -314,16 +314,16 @@ +@@ -314,16 +314,15 @@ struct res_lib_confdb_key_change_callback *res_key_changed_pt; struct res_lib_confdb_object_create_callback *res_object_created_pt; struct res_lib_confdb_object_destroy_callback *res_object_destroyed_pt; - struct res_overlay dispatch_data; +- int ignore_dispatch = 0; + struct confdb_res_overlay dispatch_data; - int ignore_dispatch = 0; error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst); - if (error != SA_AIS_OK) { @@ -8441,7 +9992,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_unlock; } -@@ -341,7 +341,7 @@ +@@ -341,7 +340,7 @@ ufds.revents = 0; error = saPollRetry (&ufds, 1, timeout); @@ -8450,7 +10001,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_nounlock; } -@@ -351,7 +351,7 @@ +@@ -351,7 +350,7 @@ * Regather poll data in case ufds has changed since taking lock */ error = saPollRetry (&ufds, 1, timeout); @@ -8459,7 +10010,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_nounlock; } -@@ -359,7 +359,7 @@ +@@ -359,7 +358,7 @@ * Handle has been finalized in another thread */ if (confdb_inst->finalize == 1) { @@ -8468,7 +10019,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c pthread_mutex_unlock (&confdb_inst->dispatch_mutex); goto error_unlock; } -@@ -380,14 +380,14 @@ +@@ -380,14 +379,14 @@ */ error = saRecvRetry (confdb_inst->dispatch_fd, &dispatch_data.header, sizeof (mar_res_header_t)); @@ -8485,7 +10036,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_unlock; } } -@@ -443,7 +443,7 @@ +@@ -443,7 +442,7 @@ break; default: @@ -8494,7 +10045,25 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_nounlock; break; } -@@ -470,36 +470,36 @@ +@@ -453,16 +452,9 @@ + * */ + switch (dispatch_types) { + case CONFDB_DISPATCH_ONE: +- if (ignore_dispatch) { +- ignore_dispatch = 0; +- } else { +- cont = 0; +- } ++ cont = 0; + break; + case CONFDB_DISPATCH_ALL: +- if (ignore_dispatch) { +- ignore_dispatch = 0; +- } + break; + case CONFDB_DISPATCH_BLOCKING: + break; +@@ -470,36 +462,36 @@ } while (cont); error_unlock: @@ -8537,7 +10106,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -518,7 +518,7 @@ +@@ -518,7 +510,7 @@ &res_lib_confdb_object_create, sizeof (struct res_lib_confdb_object_create)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -8546,7 +10115,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -526,31 +526,31 @@ +@@ -526,31 +518,31 @@ *object_handle = res_lib_confdb_object_create.object_handle; error_exit: @@ -8584,7 +10153,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -567,39 +567,39 @@ +@@ -567,39 +559,39 @@ &res, sizeof ( mar_res_header_t)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -8631,7 +10200,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -616,7 +616,7 @@ +@@ -616,7 +608,7 @@ &res_lib_confdb_object_parent_get, sizeof (struct res_lib_confdb_object_parent_get)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -8640,7 +10209,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -624,28 +624,28 @@ +@@ -624,28 +616,28 @@ *parent_object_handle = res_lib_confdb_object_parent_get.parent_object_handle; error_exit: @@ -8675,7 +10244,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -662,7 +662,7 @@ +@@ -662,7 +654,7 @@ &res, sizeof (mar_res_header_t)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -8684,7 +10253,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -673,56 +673,56 @@ +@@ -673,56 +665,56 @@ return (error); } @@ -8752,7 +10321,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c confdb_handle_t handle, unsigned int parent_object_handle, void *key_name, -@@ -730,24 +730,24 @@ +@@ -730,24 +722,24 @@ void *value, int value_len) { @@ -8781,7 +10350,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -768,19 +768,19 @@ +@@ -768,19 +760,19 @@ &res, sizeof (res)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -8804,7 +10373,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c confdb_handle_t handle, unsigned int parent_object_handle, void *key_name, -@@ -788,24 +788,24 @@ +@@ -788,24 +780,24 @@ void *value, int value_len) { @@ -8833,7 +10402,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -826,19 +826,19 @@ +@@ -826,19 +818,19 @@ &res, sizeof (res)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -8856,7 +10425,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c confdb_handle_t handle, unsigned int parent_object_handle, void *key_name, -@@ -846,24 +846,24 @@ +@@ -846,24 +838,24 @@ void *value, int *value_len) { @@ -8885,7 +10454,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -882,47 +882,47 @@ +@@ -882,47 +874,47 @@ &res_lib_confdb_key_get, sizeof (struct res_lib_confdb_key_get)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -8941,7 +10510,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -941,46 +941,46 @@ +@@ -941,46 +933,46 @@ &res_lib_confdb_key_incdec, sizeof (struct res_lib_confdb_key_incdec)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -8996,7 +10565,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -999,22 +999,22 @@ +@@ -999,22 +991,22 @@ &res_lib_confdb_key_incdec, sizeof (struct res_lib_confdb_key_incdec)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -9023,7 +10592,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c confdb_handle_t handle, unsigned int parent_object_handle, void *key_name, -@@ -1024,25 +1024,25 @@ +@@ -1024,25 +1016,25 @@ void *new_value, int new_value_len) { @@ -9053,7 +10622,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } req_lib_confdb_key_replace.header.size = sizeof (struct req_lib_confdb_key_replace); -@@ -1064,28 +1064,28 @@ +@@ -1064,28 +1056,28 @@ &res, sizeof (res)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -9087,7 +10656,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c return (error); } -@@ -1093,7 +1093,7 @@ +@@ -1093,7 +1085,7 @@ if (!context) { context = malloc(sizeof(struct iter_context)); if (!context) { @@ -9096,7 +10665,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto ret; } context->parent_object_handle = object_handle; -@@ -1103,26 +1103,26 @@ +@@ -1103,26 +1095,26 @@ /* Start a new find context */ if (context->find_handle) { @@ -9128,7 +10697,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c return (error); } -@@ -1130,7 +1130,7 @@ +@@ -1130,7 +1122,7 @@ if (!context) { context = malloc(sizeof(struct iter_context)); if (!context) { @@ -9137,7 +10706,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto ret; } context->parent_object_handle = object_handle; -@@ -1140,22 +1140,22 @@ +@@ -1140,22 +1132,22 @@ context->find_handle = 0; context->next_entry = 0; @@ -9164,7 +10733,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c return (error); } -@@ -1163,7 +1163,7 @@ +@@ -1163,7 +1155,7 @@ if (!context) { context = malloc(sizeof(struct iter_context)); if (!context) { @@ -9173,7 +10742,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto ret; } context->find_handle = 0; -@@ -1172,24 +1172,24 @@ +@@ -1172,24 +1164,24 @@ } /* Start a new find context */ if (context->find_handle) { @@ -9202,7 +10771,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c struct confdb_inst *confdb_inst; struct iovec iov[2]; struct iter_context *context; -@@ -1197,26 +1197,26 @@ +@@ -1197,26 +1189,26 @@ struct res_lib_confdb_object_find res_lib_confdb_object_find; error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst); @@ -9233,7 +10802,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -1236,7 +1236,7 @@ +@@ -1236,7 +1228,7 @@ &res_lib_confdb_object_find, sizeof (struct res_lib_confdb_object_find)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -9242,7 +10811,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -1245,20 +1245,20 @@ +@@ -1245,20 +1237,20 @@ context->find_handle = res_lib_confdb_object_find.find_handle; error_exit: @@ -9266,7 +10835,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c struct confdb_inst *confdb_inst; struct iovec iov[2]; struct iter_context *context; -@@ -1266,19 +1266,19 @@ +@@ -1266,19 +1258,19 @@ struct res_lib_confdb_object_iter res_lib_confdb_object_iter; error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst); @@ -9289,7 +10858,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c *object_name_len = 0; if (confdb_sa_object_find(parent_object_handle, -@@ -1286,7 +1286,7 @@ +@@ -1286,7 +1278,7 @@ object_handle, object_name, object_name_len, 1)) @@ -9298,7 +10867,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto sa_exit; } -@@ -1304,12 +1304,12 @@ +@@ -1304,12 +1296,12 @@ &res_lib_confdb_object_iter, sizeof (struct res_lib_confdb_object_iter)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -9313,7 +10882,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c *object_name_len = res_lib_confdb_object_iter.object_name.length; memcpy(object_name, res_lib_confdb_object_iter.object_name.value, *object_name_len); *object_handle = res_lib_confdb_object_iter.object_handle; -@@ -1318,12 +1318,12 @@ +@@ -1318,12 +1310,12 @@ sa_exit: error_exit: @@ -9328,7 +10897,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c confdb_handle_t handle, unsigned int parent_object_handle, void *key_name, -@@ -1331,7 +1331,7 @@ +@@ -1331,7 +1323,7 @@ void *value, int *value_len) { @@ -9337,7 +10906,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c struct confdb_inst *confdb_inst; struct iovec iov[2]; struct iter_context *context; -@@ -1339,25 +1339,25 @@ +@@ -1339,25 +1331,25 @@ struct res_lib_confdb_key_iter res_lib_confdb_key_iter; error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst); @@ -9367,7 +10936,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto sa_exit; } -@@ -1375,12 +1375,12 @@ +@@ -1375,12 +1367,12 @@ &res_lib_confdb_key_iter, sizeof (struct res_lib_confdb_key_iter)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -9382,7 +10951,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c *key_name_len = res_lib_confdb_key_iter.key_name.length; memcpy(key_name, res_lib_confdb_key_iter.key_name.value, *key_name_len); *value_len = res_lib_confdb_key_iter.value.length; -@@ -1391,31 +1391,31 @@ +@@ -1391,31 +1383,31 @@ context->next_entry++; error_exit: @@ -9420,7 +10989,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -1431,7 +1431,7 @@ +@@ -1431,7 +1423,7 @@ &res_lib_confdb_write, sizeof ( struct res_lib_confdb_write)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -9429,7 +10998,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -1440,32 +1440,32 @@ +@@ -1440,32 +1432,32 @@ memcpy(error_text, res_lib_confdb_write.error.value, res_lib_confdb_write.error.length); error_exit: @@ -9468,7 +11037,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -1483,7 +1483,7 @@ +@@ -1483,7 +1475,7 @@ pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -9477,7 +11046,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -1492,29 +1492,29 @@ +@@ -1492,29 +1484,29 @@ memcpy(error_text, res_lib_confdb_reload.error.value, res_lib_confdb_reload.error.length); error_exit: @@ -9512,7 +11081,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -1532,33 +1532,33 @@ +@@ -1532,33 +1524,33 @@ &res, sizeof ( mar_res_header_t)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -9552,7 +11121,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c goto error_exit; } -@@ -1574,14 +1574,14 @@ +@@ -1574,14 +1566,14 @@ &res, sizeof ( mar_res_header_t)); pthread_mutex_unlock (&confdb_inst->response_mutex); @@ -9571,7 +11140,7 @@ diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c } diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c --- corosync-0.92/lib/cpg.c 2008-09-17 21:15:00.000000000 +0200 -+++ corosync-trunk/lib/cpg.c 2008-11-11 18:26:58.000000000 +0100 ++++ corosync-trunk/lib/cpg.c 2009-01-08 07:29:16.000000000 +0100 @@ -45,7 +45,7 @@ #include #include @@ -9769,16 +11338,17 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c int cont = 1; /* always continue do loop except when set to 0 */ int dispatch_avail; struct cpg_inst *cpg_inst; -@@ -253,7 +253,7 @@ +@@ -253,8 +253,7 @@ struct res_lib_cpg_deliver_callback *res_cpg_deliver_callback; struct res_lib_cpg_groups_get_callback *res_lib_cpg_groups_get_callback; cpg_callbacks_t callbacks; - struct res_overlay dispatch_data; +- int ignore_dispatch = 0; + struct cpg_res_overlay dispatch_data; - int ignore_dispatch = 0; struct cpg_address member_list[CPG_MEMBERS_MAX]; struct cpg_address left_list[CPG_MEMBERS_MAX]; -@@ -264,7 +264,7 @@ + struct cpg_address joined_list[CPG_MEMBERS_MAX]; +@@ -264,7 +263,7 @@ unsigned int i; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); @@ -9787,7 +11357,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c return (error); } -@@ -272,7 +272,7 @@ +@@ -272,7 +271,7 @@ * Timeout instantly for SA_DISPATCH_ONE or SA_DISPATCH_ALL and * wait indefinately for SA_DISPATCH_BLOCKING */ @@ -9796,7 +11366,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c timeout = 0; } -@@ -282,7 +282,7 @@ +@@ -282,7 +281,7 @@ ufds.revents = 0; error = saPollRetry (&ufds, 1, timeout); @@ -9805,7 +11375,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c goto error_nounlock; } -@@ -292,7 +292,7 @@ +@@ -292,7 +291,7 @@ * Regather poll data in case ufds has changed since taking lock */ error = saPollRetry (&ufds, 1, timeout); @@ -9814,7 +11384,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c goto error_nounlock; } -@@ -300,13 +300,13 @@ +@@ -300,13 +299,13 @@ * Handle has been finalized in another thread */ if (cpg_inst->finalize == 1) { @@ -9830,7 +11400,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c pthread_mutex_unlock (&cpg_inst->dispatch_mutex); break; /* exit do while cont is 1 loop */ } else -@@ -321,14 +321,14 @@ +@@ -321,14 +320,14 @@ */ error = saRecvRetry (cpg_inst->dispatch_fd, &dispatch_data.header, sizeof (mar_res_header_t)); @@ -9847,7 +11417,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c goto error_unlock; } } -@@ -424,7 +424,7 @@ +@@ -424,7 +423,7 @@ break; default: @@ -9856,23 +11426,24 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c goto error_nounlock; break; } -@@ -433,34 +433,34 @@ +@@ -433,34 +432,27 @@ * Determine if more messages should be processed * */ switch (dispatch_types) { - case CPG_DISPATCH_ONE: +- if (ignore_dispatch) { +- ignore_dispatch = 0; +- } else { +- cont = 0; +- } + case CS_DISPATCH_ONE: - if (ignore_dispatch) { - ignore_dispatch = 0; - } else { - cont = 0; - } ++ cont = 0; break; - case CPG_DISPATCH_ALL: +- if (ignore_dispatch) { +- ignore_dispatch = 0; +- } + case CS_DISPATCH_ALL: - if (ignore_dispatch) { - ignore_dispatch = 0; - } break; - case CPG_DISPATCH_BLOCKING: + case CS_DISPATCH_BLOCKING: @@ -9897,7 +11468,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c struct cpg_inst *cpg_inst; struct iovec iov[2]; struct req_lib_cpg_join req_lib_cpg_join; -@@ -469,7 +469,7 @@ +@@ -469,7 +461,7 @@ struct res_lib_cpg_trackstart res_lib_cpg_trackstart; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); @@ -9906,7 +11477,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c return (error); } -@@ -487,7 +487,7 @@ +@@ -487,7 +479,7 @@ error = saSendMsgReceiveReply (cpg_inst->dispatch_fd, iov, 1, &res_lib_cpg_trackstart, sizeof (struct res_lib_cpg_trackstart)); @@ -9915,7 +11486,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c pthread_mutex_unlock (&cpg_inst->response_mutex); goto error_exit; } -@@ -507,30 +507,30 @@ +@@ -507,30 +499,30 @@ pthread_mutex_unlock (&cpg_inst->response_mutex); @@ -9951,7 +11522,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c return (error); } -@@ -549,26 +549,26 @@ +@@ -549,26 +541,26 @@ &res_lib_cpg_leave, sizeof (struct res_lib_cpg_leave)); pthread_mutex_unlock (&cpg_inst->response_mutex); @@ -9982,7 +11553,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c struct cpg_inst *cpg_inst; struct iovec iov[64]; struct req_lib_cpg_mcast req_lib_cpg_mcast; -@@ -576,7 +576,7 @@ +@@ -576,7 +568,7 @@ int msg_len = 0; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); @@ -9991,7 +11562,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c return (error); } -@@ -602,7 +602,7 @@ +@@ -602,7 +594,7 @@ pthread_mutex_unlock (&cpg_inst->response_mutex); @@ -10000,7 +11571,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c goto error_exit; } -@@ -612,24 +612,24 @@ +@@ -612,85 +604,108 @@ * Also, don't set to ENABLED if the return value is TRY_AGAIN as this can lead * to Flow Control State sync issues between AIS LIB and EXEC. */ @@ -10029,8 +11600,12 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c struct cpg_inst *cpg_inst; struct iovec iov; struct req_lib_cpg_membership req_lib_cpg_membership_get; -@@ -637,7 +637,7 @@ - unsigned int i; +- struct res_lib_cpg_confchg_callback res_lib_cpg_membership_get; +- unsigned int i; ++ struct res_lib_cpg_confchg_callback *res_lib_cpg_membership_get; ++ mar_res_header_t header; ++ unsigned int i, bytesleft; ++ char *buffer = NULL; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); - if (error != SA_AIS_OK) { @@ -10038,20 +11613,72 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c return (error); } -@@ -656,7 +656,7 @@ +- req_lib_cpg_membership_get.header.size = sizeof (mar_req_header_t); ++ req_lib_cpg_membership_get.header.size = sizeof (req_lib_cpg_membership_get); + req_lib_cpg_membership_get.header.id = MESSAGE_REQ_CPG_MEMBERSHIP; +- marshall_to_mar_cpg_name_t (&req_lib_cpg_membership_get.group_name, +- group_name); - pthread_mutex_unlock (&cpg_inst->response_mutex); + iov.iov_base = (char *)&req_lib_cpg_membership_get; +- iov.iov_len = sizeof (mar_req_header_t); ++ iov.iov_len = sizeof (req_lib_cpg_membership_get); + + pthread_mutex_lock (&cpg_inst->response_mutex); + + error = saSendMsgReceiveReply (cpg_inst->response_fd, &iov, 1, +- &res_lib_cpg_membership_get, sizeof (mar_res_header_t)); ++ &header, sizeof (header)); ++ if (error != CS_OK) { ++ goto error_exit; ++ } + +- pthread_mutex_unlock (&cpg_inst->response_mutex); ++ buffer = malloc(header.size); ++ if (buffer == NULL) { ++ error = CS_ERR_NO_MEMORY; ++ goto error_exit; ++ } - if (error != SA_AIS_OK) { ++ memcpy (buffer, &header, sizeof (header)); ++ bytesleft = header.size - sizeof (header); ++ ++ error = saRecvRetry (cpg_inst->response_fd, ++ buffer + sizeof (header), bytesleft); + if (error != CS_OK) { goto error_exit; } -@@ -674,23 +674,23 @@ +- error = res_lib_cpg_membership_get.header.error; ++ error = header.error; ++ if (error != CS_OK) { ++ goto error_exit; ++ } ++ ++ res_lib_cpg_membership_get = (struct res_lib_cpg_confchg_callback *) buffer; + + /* + * Copy results to caller + */ +- *member_list_entries = res_lib_cpg_membership_get.member_list_entries; ++ *member_list_entries = res_lib_cpg_membership_get->member_list_entries; + if (member_list) { +- for (i = 0; i < res_lib_cpg_membership_get.member_list_entries; i++) { ++ for (i = 0; i < res_lib_cpg_membership_get->member_list_entries; i++) { + marshall_from_mar_cpg_address_t (&member_list[i], +- &res_lib_cpg_membership_get.member_list[i]); ++ &res_lib_cpg_membership_get->member_list[i]); + } } error_exit: - saHandleInstancePut (&cpg_handle_t_db, handle); ++ ++ if (buffer != NULL) ++ free(buffer); ++ ++ pthread_mutex_unlock (&cpg_inst->response_mutex); ++ + (void)saHandleInstancePut (&cpg_handle_t_db, handle); return (error); @@ -10075,7 +11702,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c return (error); } -@@ -707,7 +707,7 @@ +@@ -707,7 +722,7 @@ pthread_mutex_unlock (&cpg_inst->response_mutex); @@ -10084,7 +11711,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c goto error_exit; } -@@ -716,23 +716,23 @@ +@@ -716,23 +731,23 @@ *local_nodeid = res_lib_cpg_local_get.local_nodeid; error_exit: @@ -10112,7 +11739,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c return (error); } -@@ -749,7 +749,7 @@ +@@ -749,7 +764,7 @@ pthread_mutex_unlock (&cpg_inst->response_mutex); @@ -10121,7 +11748,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c goto error_exit; } -@@ -758,26 +758,26 @@ +@@ -758,26 +773,26 @@ /* Real output is delivered via a callback */ error_exit: @@ -10155,7 +11782,7 @@ diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c } diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c --- corosync-0.92/lib/evs.c 2008-08-14 18:54:46.000000000 +0200 -+++ corosync-trunk/lib/evs.c 2008-11-11 18:26:58.000000000 +0100 ++++ corosync-trunk/lib/evs.c 2008-12-28 10:25:17.000000000 +0100 @@ -48,7 +48,7 @@ #include @@ -10263,7 +11890,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c /* * Disconnect from the server */ -@@ -180,49 +180,49 @@ +@@ -180,49 +180,48 @@ shutdown(evs_inst->dispatch_fd, 0); close(evs_inst->dispatch_fd); } @@ -10316,8 +11943,8 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c struct res_evs_deliver_callback *res_evs_deliver_callback; evs_callbacks_t callbacks; - struct res_overlay dispatch_data; +- int ignore_dispatch = 0; + struct evs_res_overlay dispatch_data; - int ignore_dispatch = 0; error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst); - if (error != SA_AIS_OK) { @@ -10325,7 +11952,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c return (error); } -@@ -230,7 +230,7 @@ +@@ -230,7 +229,7 @@ * Timeout instantly for SA_DISPATCH_ONE or SA_DISPATCH_ALL and * wait indefinately for SA_DISPATCH_BLOCKING */ @@ -10334,7 +11961,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c timeout = 0; } -@@ -240,7 +240,7 @@ +@@ -240,7 +239,7 @@ ufds.revents = 0; error = saPollRetry (&ufds, 1, timeout); @@ -10343,7 +11970,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c goto error_nounlock; } -@@ -250,7 +250,7 @@ +@@ -250,7 +249,7 @@ * Regather poll data in case ufds has changed since taking lock */ error = saPollRetry (&ufds, 1, 0); @@ -10352,7 +11979,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c goto error_nounlock; } -@@ -258,13 +258,13 @@ +@@ -258,13 +257,13 @@ * Handle has been finalized in another thread */ if (evs_inst->finalize == 1) { @@ -10368,7 +11995,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c pthread_mutex_unlock (&evs_inst->dispatch_mutex); break; /* exit do while cont is 1 loop */ } else -@@ -279,14 +279,14 @@ +@@ -279,14 +278,14 @@ */ error = saRecvRetry (evs_inst->dispatch_fd, &dispatch_data.header, sizeof (mar_res_header_t)); @@ -10385,7 +12012,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c goto error_unlock; } } -@@ -327,7 +327,7 @@ +@@ -327,7 +326,7 @@ break; default: @@ -10394,23 +12021,24 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c goto error_nounlock; break; } -@@ -336,42 +336,42 @@ +@@ -336,42 +335,35 @@ * Determine if more messages should be processed * */ switch (dispatch_types) { - case EVS_DISPATCH_ONE: +- if (ignore_dispatch) { +- ignore_dispatch = 0; +- } else { +- cont = 0; +- } + case CS_DISPATCH_ONE: - if (ignore_dispatch) { - ignore_dispatch = 0; - } else { - cont = 0; - } ++ cont = 0; break; - case EVS_DISPATCH_ALL: +- if (ignore_dispatch) { +- ignore_dispatch = 0; +- } + case CS_DISPATCH_ALL: - if (ignore_dispatch) { - ignore_dispatch = 0; - } break; - case EVS_DISPATCH_BLOCKING: + case CS_DISPATCH_BLOCKING: @@ -10444,7 +12072,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c return (error); } -@@ -392,31 +392,31 @@ +@@ -392,31 +384,31 @@ pthread_mutex_unlock (&evs_inst->response_mutex); @@ -10481,7 +12109,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c return (error); } -@@ -437,26 +437,26 @@ +@@ -437,26 +429,26 @@ pthread_mutex_unlock (&evs_inst->response_mutex); @@ -10512,7 +12140,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c struct evs_inst *evs_inst; struct iovec iov[64]; struct req_lib_evs_mcast_joined req_lib_evs_mcast_joined; -@@ -464,7 +464,7 @@ +@@ -464,7 +456,7 @@ int msg_len = 0; error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst); @@ -10521,7 +12149,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c return (error); } -@@ -490,19 +490,19 @@ +@@ -490,19 +482,19 @@ pthread_mutex_unlock (&evs_inst->response_mutex); @@ -10544,7 +12172,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c evs_handle_t handle, evs_guarantee_t guarantee, struct evs_group *groups, -@@ -511,7 +511,7 @@ +@@ -511,7 +503,7 @@ int iov_len) { int i; @@ -10553,7 +12181,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c struct evs_inst *evs_inst; struct iovec iov[64]; struct req_lib_evs_mcast_groups req_lib_evs_mcast_groups; -@@ -519,7 +519,7 @@ +@@ -519,7 +511,7 @@ int msg_len = 0; error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst); @@ -10562,7 +12190,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c return (error); } for (i = 0; i < iov_len; i++) { -@@ -544,32 +544,32 @@ +@@ -544,32 +536,32 @@ &res_lib_evs_mcast_groups, sizeof (struct res_lib_evs_mcast_groups)); pthread_mutex_unlock (&evs_inst->response_mutex); @@ -10600,7 +12228,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c return (error); } -@@ -586,7 +586,7 @@ +@@ -586,7 +578,7 @@ pthread_mutex_unlock (&evs_inst->response_mutex); @@ -10609,7 +12237,7 @@ diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c goto error_exit; } -@@ -606,7 +606,7 @@ +@@ -606,7 +598,7 @@ } error_exit: @@ -10645,24 +12273,18 @@ diff -Naurd corosync-0.92/lib/libpload.versions corosync-trunk/lib/libpload.vers +}; diff -Naurd corosync-0.92/lib/libquorum.versions corosync-trunk/lib/libquorum.versions --- corosync-0.92/lib/libquorum.versions 1970-01-01 01:00:00.000000000 +0100 -+++ corosync-trunk/lib/libquorum.versions 2008-12-08 16:55:41.000000000 +0100 -@@ -0,0 +1,59 @@ ++++ corosync-trunk/lib/libquorum.versions 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,50 @@ +# Version and symbol export for libquorum.so + +OPENAIS_QUORUM_1.0 { + global: + quorum_initialize; + quorum_finalize; -+ quorum_getinfo; -+ quorum_setexpected; -+ quorum_setvotes; -+ quorum_qdisk_register; -+ quorum_qdisk_unregister; -+ quorum_qdisk_poll; -+ quorum_qdisk_getinfo; -+ quorum_setdirty; -+ quorum_killnode; -+ quorum_leaving; ++ quorum_getquorate; ++ quorum_initialize; ++ quorum_finalize; ++ quorum_dispatch; + + local: + saHandleCreate; @@ -10679,17 +12301,89 @@ diff -Naurd corosync-0.92/lib/libquorum.versions corosync-trunk/lib/libquorum.ve + saVersionVerify; + clustTimeNow; +}; -+# Version and symbol export for libcpg.so ++# Version and symbol export for libquorum.so + +COROSYNC_QUORUM_1.0 { + global: + quorum_initialize; + quorum_finalize; -+ quorum_fd_get; ++ quorum_getquorate; + quorum_dispatch; -+ quorum_get_quorate; -+ quorum_context_get; -+ quorum_context_set; ++ ++ local: ++ saHandleCreate; ++ saHandleDestroy; ++ saHandleInstanceGet; ++ saHandleInstancePut; ++ saRecvRetry; ++ saSelectRetry; ++ saSendMsgReceiveReply; ++ saSendMsgRetry; ++ saSendReceiveReply; ++ saSendRetry; ++ saServiceConnect; ++ saVersionVerify; ++ clustTimeNow; ++}; +diff -Naurd corosync-0.92/lib/libvotequorum.versions corosync-trunk/lib/libvotequorum.versions +--- corosync-0.92/lib/libvotequorum.versions 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/lib/libvotequorum.versions 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,71 @@ ++# Version and symbol export for libvotequorum.so ++ ++OPENAIS_VOTEQUORUM_1.0 { ++ global: ++ votequorum_initialize; ++ votequorum_finalize; ++ votequorum_getinfo; ++ votequorum_setexpected; ++ votequorum_setvotes; ++ votequorum_qdisk_register; ++ votequorum_qdisk_unregister; ++ votequorum_qdisk_poll; ++ votequorum_qdisk_getinfo; ++ votequorum_setstate; ++ votequorum_leaving; ++ votequorum_trackstart; ++ votequorum_trackstop; ++ votequorum_context_get; ++ votequorum_context_set; ++ ++ local: ++ saHandleCreate; ++ saHandleDestroy; ++ saHandleInstanceGet; ++ saHandleInstancePut; ++ saRecvRetry; ++ saSelectRetry; ++ saSendMsgReceiveReply; ++ saSendMsgRetry; ++ saSendReceiveReply; ++ saSendRetry; ++ saServiceConnect; ++ saVersionVerify; ++ clustTimeNow; ++}; ++# Version and symbol export for libvotequorum.so ++ ++COROSYNC_VOTEQUORUM_1.0 { ++ global: ++ votequorum_initialize; ++ votequorum_finalize; ++ votequorum_getinfo; ++ votequorum_setexpected; ++ votequorum_setvotes; ++ votequorum_qdisk_register; ++ votequorum_qdisk_unregister; ++ votequorum_qdisk_poll; ++ votequorum_qdisk_getinfo; ++ votequorum_setdirty; ++ votequorum_killnode; ++ votequorum_leaving; ++ votequorum_trackstart; ++ votequorum_trackstop; ++ votequorum_context_get; ++ votequorum_context_set; + + local: + saHandleCreate; @@ -10708,22 +12402,28 @@ diff -Naurd corosync-0.92/lib/libquorum.versions corosync-trunk/lib/libquorum.ve +}; diff -Naurd corosync-0.92/lib/Makefile corosync-trunk/lib/Makefile --- corosync-0.92/lib/Makefile 2008-08-15 08:15:26.000000000 +0200 -+++ corosync-trunk/lib/Makefile 2008-11-04 02:35:15.000000000 +0100 -@@ -41,6 +41,8 @@ ++++ corosync-trunk/lib/Makefile 2009-01-26 11:46:08.000000000 +0100 +@@ -41,7 +41,10 @@ libconfdb.a libconfdb.so.2.0.0 \ libevs.a libevs.so.2.0.0 \ libcfg.a libcfg.so.2.0.0 \ +- libcoroutil.a libcoroutil.so.2.0.0 + libquorum.a libquorum.so.2.0.0 \ + libpload.a libpload.so.2.0.0 \ - libcoroutil.a libcoroutil.so.2.0.0 ++ libcoroutil.a libcoroutil.so.2.0.0 \ ++ libvotequorum.a libvotequorum.so.2.0.0 libcoroutil.a: util.o -@@ -58,14 +60,17 @@ + $(AR) -rc libcoroutil.a util.o +@@ -58,14 +61,20 @@ libcpg.so.2.0.0: util.o cpg.o $(CC) $(DARWIN_OPTS) util.o cpg.o -o $@ +libquorum.so.2.0.0: util.o quorum.o + $(CC) $(DARWIN_OPTS) util.o quorum.o -o $@ ++ ++libvotequorum.so.2.0.0: util.o votequorum.o ++ $(CC) $(DARWIN_OPTS) util.o votequorum.o -o $@ + libconfdb.so.2.0.0: util.o confdb.o sa-confdb.o $(CC) $(LDFLAGS) $(DARWIN_OPTS) util.o confdb.o sa-confdb.o ../lcr/lcr_ifact.o -o $@ @@ -10738,12 +12438,15 @@ diff -Naurd corosync-0.92/lib/Makefile corosync-trunk/lib/Makefile else -@@ -78,12 +83,18 @@ +@@ -78,12 +87,21 @@ libcpg.so.2.0.0: util.o cpg.o $(CC) -shared -Wl,-soname,libcpg.so.2,-version-script=$(srcdir)$(subdir)libcpg.versions util.o cpg.o -o $@ +libquorum.so.2.0.0: util.o quorum.o + $(CC) -shared -Wl,-soname,libquorum.so.2,-version-script=$(srcdir)$(subdir)libquorum.versions util.o quorum.o -o $@ ++ ++libvotequorum.so.2.0.0: util.o votequorum.o ++ $(CC) -shared -Wl,-soname,libvotequorum.so.2,-version-script=$(srcdir)$(subdir)libvotequorum.versions util.o votequorum.o -o $@ + libconfdb.so.2.0.0: util.o confdb.o sa-confdb.o $(CC) $(LDFLAGS) -shared -Wl,-soname,libconfdb.so.2,-version-script=$(srcdir)$(subdir)libconfdb.versions util.o confdb.o sa-confdb.o ../lcr/lcr_ifact.o -o $@ @@ -10757,12 +12460,15 @@ diff -Naurd corosync-0.92/lib/Makefile corosync-trunk/lib/Makefile endif libevs.a: util.o evs.o -@@ -92,17 +103,24 @@ +@@ -92,17 +110,27 @@ libcpg.a: util.o cpg.o $(AR) -rc libcpg.a util.o cpg.o +libquorum.a: util.o quorum.o + $(AR) -rc libquorum.a util.o quorum.o ++ ++libvotequorum.a: util.o votequorum.o ++ $(AR) -rc libvotequorum.a util.o votequorum.o + libconfdb.a: util.o confdb.o sa-confdb.o $(AR) -rc libconfdb.a util.o confdb.o sa-confdb.o ../lcr/lcr_ifact.o @@ -12205,13 +13911,839 @@ diff -Naurd corosync-0.92/lib/util.h corosync-trunk/lib/util.h saVersionVerify ( struct saVersionDatabase *versionDatabase, SaVersionT *version); +diff -Naurd corosync-0.92/lib/votequorum.c corosync-trunk/lib/votequorum.c +--- corosync-0.92/lib/votequorum.c 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/lib/votequorum.c 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,821 @@ ++/* ++ * Copyright (c) 2009 Red Hat, Inc. ++ * ++ * All rights reserved. ++ * ++ * Author: Christine Caulfield (ccaulfie@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 CONTIBUTORS "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. ++ */ ++ ++/* ++ * Provides a quorum API using the corosync executive ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include "corosync/votequorum.h" ++#include "corosync/ipc_votequorum.h" ++ ++struct votequorum_inst { ++ int response_fd; ++ int dispatch_fd; ++ int finalize; ++ void *context; ++ votequorum_callbacks_t callbacks; ++ pthread_mutex_t response_mutex; ++ pthread_mutex_t dispatch_mutex; ++}; ++ ++static void votequorum_instance_destructor (void *instance); ++ ++static struct saHandleDatabase votequorum_handle_t_db = { ++ .handleCount = 0, ++ .handles = 0, ++ .mutex = PTHREAD_MUTEX_INITIALIZER, ++ .handleInstanceDestructor = votequorum_instance_destructor ++}; ++ ++/* ++ * Clean up function for a quorum instance (votequorum_initialize) handle ++ */ ++static void votequorum_instance_destructor (void *instance) ++{ ++ struct votequorum_inst *votequorum_inst = instance; ++ ++ pthread_mutex_destroy (&votequorum_inst->response_mutex); ++} ++ ++cs_error_t votequorum_initialize ( ++ votequorum_handle_t *handle, ++ votequorum_callbacks_t *callbacks) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ ++ error = saHandleCreate (&votequorum_handle_t_db, sizeof (struct votequorum_inst), handle); ++ if (error != CS_OK) { ++ goto error_no_destroy; ++ } ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, *handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ goto error_destroy; ++ } ++ ++ error = saServiceConnect (&votequorum_inst->dispatch_fd, ++ &votequorum_inst->response_fd, ++ VOTEQUORUM_SERVICE); ++ if (error != CS_OK) { ++ goto error_put_destroy; ++ } ++ ++ pthread_mutex_init (&votequorum_inst->response_mutex, NULL); ++ pthread_mutex_init (&votequorum_inst->dispatch_mutex, NULL); ++ if (callbacks) ++ memcpy(&votequorum_inst->callbacks, callbacks, sizeof (callbacks)); ++ else ++ memset(&votequorum_inst->callbacks, 0, sizeof (callbacks)); ++ ++ saHandleInstancePut (&votequorum_handle_t_db, *handle); ++ ++ return (CS_OK); ++ ++error_put_destroy: ++ saHandleInstancePut (&votequorum_handle_t_db, *handle); ++error_destroy: ++ saHandleDestroy (&votequorum_handle_t_db, *handle); ++error_no_destroy: ++ return (error); ++} ++ ++cs_error_t votequorum_finalize ( ++ votequorum_handle_t handle) ++{ ++ struct votequorum_inst *votequorum_inst; ++ cs_error_t error; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ pthread_mutex_lock (&votequorum_inst->response_mutex); ++ ++ /* ++ * Another thread has already started finalizing ++ */ ++ if (votequorum_inst->finalize) { ++ pthread_mutex_unlock (&votequorum_inst->response_mutex); ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ return (CS_ERR_BAD_HANDLE); ++ } ++ ++ votequorum_inst->finalize = 1; ++ ++ pthread_mutex_unlock (&votequorum_inst->response_mutex); ++ ++ saHandleDestroy (&votequorum_handle_t_db, handle); ++ ++ /* ++ * Disconnect from the server ++ */ ++ if (votequorum_inst->response_fd != -1) { ++ shutdown(votequorum_inst->response_fd, 0); ++ close(votequorum_inst->response_fd); ++ } ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (CS_OK); ++} ++ ++ ++cs_error_t votequorum_getinfo ( ++ votequorum_handle_t handle, ++ unsigned int nodeid, ++ struct votequorum_info *info) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ struct iovec iov[2]; ++ struct req_lib_votequorum_getinfo req_lib_votequorum_getinfo; ++ struct res_lib_votequorum_getinfo res_lib_votequorum_getinfo; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ pthread_mutex_lock (&votequorum_inst->response_mutex); ++ ++ req_lib_votequorum_getinfo.header.size = sizeof (struct req_lib_votequorum_getinfo); ++ req_lib_votequorum_getinfo.header.id = MESSAGE_REQ_VOTEQUORUM_GETINFO; ++ req_lib_votequorum_getinfo.nodeid = nodeid; ++ ++ iov[0].iov_base = (char *)&req_lib_votequorum_getinfo; ++ iov[0].iov_len = sizeof (struct req_lib_votequorum_getinfo); ++ ++ error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1, ++ &res_lib_votequorum_getinfo, sizeof (struct res_lib_votequorum_getinfo)); ++ ++ pthread_mutex_unlock (&votequorum_inst->response_mutex); ++ ++ if (error != CS_OK) { ++ goto error_exit; ++ } ++ ++ error = res_lib_votequorum_getinfo.header.error; ++ ++ info->node_id = res_lib_votequorum_getinfo.nodeid; ++ info->node_votes = res_lib_votequorum_getinfo.votes; ++ info->node_expected_votes = res_lib_votequorum_getinfo.expected_votes; ++ info->highest_expected = res_lib_votequorum_getinfo.highest_expected; ++ info->total_votes = res_lib_votequorum_getinfo.total_votes; ++ info->quorum = res_lib_votequorum_getinfo.quorum; ++ info->flags = res_lib_votequorum_getinfo.flags; ++ ++error_exit: ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (error); ++} ++ ++cs_error_t votequorum_setexpected ( ++ votequorum_handle_t handle, ++ unsigned int expected_votes) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ struct iovec iov[2]; ++ struct req_lib_votequorum_setexpected req_lib_votequorum_setexpected; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ pthread_mutex_lock (&votequorum_inst->response_mutex); ++ ++ req_lib_votequorum_setexpected.header.size = sizeof (struct req_lib_votequorum_setexpected); ++ req_lib_votequorum_setexpected.header.id = MESSAGE_REQ_VOTEQUORUM_SETEXPECTED; ++ req_lib_votequorum_setexpected.expected_votes = expected_votes; ++ ++ iov[0].iov_base = (char *)&req_lib_votequorum_setexpected; ++ iov[0].iov_len = sizeof (struct req_lib_votequorum_setexpected); ++ ++ error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1, ++ &res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status)); ++ ++ pthread_mutex_unlock (&votequorum_inst->response_mutex); ++ ++ if (error != CS_OK) { ++ goto error_exit; ++ } ++ ++ error = res_lib_votequorum_status.header.error; ++ ++error_exit: ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (error); ++} ++ ++cs_error_t votequorum_setvotes ( ++ votequorum_handle_t handle, ++ unsigned int nodeid, ++ unsigned int votes) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ struct iovec iov[2]; ++ struct req_lib_votequorum_setvotes req_lib_votequorum_setvotes; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ pthread_mutex_lock (&votequorum_inst->response_mutex); ++ ++ req_lib_votequorum_setvotes.header.size = sizeof (struct req_lib_votequorum_setvotes); ++ req_lib_votequorum_setvotes.header.id = MESSAGE_REQ_VOTEQUORUM_SETVOTES; ++ req_lib_votequorum_setvotes.nodeid = nodeid; ++ req_lib_votequorum_setvotes.votes = votes; ++ ++ iov[0].iov_base = (char *)&req_lib_votequorum_setvotes; ++ iov[0].iov_len = sizeof (struct req_lib_votequorum_setvotes); ++ ++ error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1, ++ &res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status)); ++ ++ pthread_mutex_unlock (&votequorum_inst->response_mutex); ++ ++ if (error != CS_OK) { ++ goto error_exit; ++ } ++ ++ error = res_lib_votequorum_status.header.error; ++ ++error_exit: ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (error); ++} ++ ++cs_error_t votequorum_qdisk_register ( ++ votequorum_handle_t handle, ++ char *name, ++ unsigned int votes) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ struct iovec iov[2]; ++ struct req_lib_votequorum_qdisk_register req_lib_votequorum_qdisk_register; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ ++ if (strlen(name) > VOTEQUORUM_MAX_QDISK_NAME_LEN) ++ return CS_ERR_INVALID_PARAM; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ pthread_mutex_lock (&votequorum_inst->response_mutex); ++ ++ req_lib_votequorum_qdisk_register.header.size = sizeof (struct req_lib_votequorum_qdisk_register); ++ req_lib_votequorum_qdisk_register.header.id = MESSAGE_REQ_VOTEQUORUM_QDISK_REGISTER; ++ strcpy(req_lib_votequorum_qdisk_register.name, name); ++ req_lib_votequorum_qdisk_register.votes = votes; ++ ++ iov[0].iov_base = (char *)&req_lib_votequorum_qdisk_register; ++ iov[0].iov_len = sizeof (struct req_lib_votequorum_qdisk_register); ++ ++ error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1, ++ &res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status)); ++ ++ pthread_mutex_unlock (&votequorum_inst->response_mutex); ++ ++ if (error != CS_OK) { ++ goto error_exit; ++ } ++ ++ error = res_lib_votequorum_status.header.error; ++ ++error_exit: ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (error); ++} ++ ++cs_error_t votequorum_qdisk_poll ( ++ votequorum_handle_t handle, ++ unsigned int state) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ struct iovec iov[2]; ++ struct req_lib_votequorum_qdisk_poll req_lib_votequorum_qdisk_poll; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ pthread_mutex_lock (&votequorum_inst->response_mutex); ++ ++ req_lib_votequorum_qdisk_poll.header.size = sizeof (struct req_lib_votequorum_qdisk_poll); ++ req_lib_votequorum_qdisk_poll.header.id = MESSAGE_REQ_VOTEQUORUM_QDISK_POLL; ++ req_lib_votequorum_qdisk_poll.state = state; ++ ++ iov[0].iov_base = (char *)&req_lib_votequorum_qdisk_poll; ++ iov[0].iov_len = sizeof (struct req_lib_votequorum_qdisk_poll); ++ ++ error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1, ++ &res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status)); ++ ++ pthread_mutex_unlock (&votequorum_inst->response_mutex); ++ ++ if (error != CS_OK) { ++ goto error_exit; ++ } ++ ++ error = res_lib_votequorum_status.header.error; ++ ++error_exit: ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (error); ++} ++ ++cs_error_t votequorum_qdisk_unregister ( ++ votequorum_handle_t handle) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ struct iovec iov[2]; ++ struct req_lib_votequorum_general req_lib_votequorum_general; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ pthread_mutex_lock (&votequorum_inst->response_mutex); ++ ++ req_lib_votequorum_general.header.size = sizeof (struct req_lib_votequorum_general); ++ req_lib_votequorum_general.header.id = MESSAGE_REQ_VOTEQUORUM_QDISK_UNREGISTER; ++ ++ iov[0].iov_base = (char *)&req_lib_votequorum_general; ++ iov[0].iov_len = sizeof (struct req_lib_votequorum_general); ++ ++ error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1, ++ &res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status)); ++ ++ pthread_mutex_unlock (&votequorum_inst->response_mutex); ++ ++ if (error != CS_OK) { ++ goto error_exit; ++ } ++ ++ error = res_lib_votequorum_status.header.error; ++ ++error_exit: ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (error); ++} ++ ++ ++ ++cs_error_t votequorum_qdisk_getinfo ( ++ votequorum_handle_t handle, ++ struct votequorum_qdisk_info *qinfo) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ struct iovec iov[2]; ++ struct req_lib_votequorum_general req_lib_votequorum_general; ++ struct res_lib_votequorum_qdisk_getinfo res_lib_votequorum_qdisk_getinfo; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ pthread_mutex_lock (&votequorum_inst->response_mutex); ++ ++ req_lib_votequorum_general.header.size = sizeof (struct req_lib_votequorum_general); ++ req_lib_votequorum_general.header.id = MESSAGE_REQ_VOTEQUORUM_QDISK_GETINFO; ++ ++ iov[0].iov_base = (char *)&req_lib_votequorum_general; ++ iov[0].iov_len = sizeof (struct req_lib_votequorum_general); ++ ++ error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1, ++ &res_lib_votequorum_qdisk_getinfo, sizeof (struct res_lib_votequorum_qdisk_getinfo)); ++ ++ pthread_mutex_unlock (&votequorum_inst->response_mutex); ++ ++ if (error != CS_OK) { ++ goto error_exit; ++ } ++ ++ error = res_lib_votequorum_qdisk_getinfo.header.error; ++ ++ qinfo->votes = res_lib_votequorum_qdisk_getinfo.votes; ++ qinfo->state = res_lib_votequorum_qdisk_getinfo.state; ++ strcpy(qinfo->name, res_lib_votequorum_qdisk_getinfo.name); ++ ++ ++error_exit: ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (error); ++} ++ ++cs_error_t votequorum_setstate ( ++ votequorum_handle_t handle) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ struct iovec iov[2]; ++ struct req_lib_votequorum_general req_lib_votequorum_general; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ pthread_mutex_lock (&votequorum_inst->response_mutex); ++ ++ req_lib_votequorum_general.header.size = sizeof (struct req_lib_votequorum_general); ++ req_lib_votequorum_general.header.id = MESSAGE_REQ_VOTEQUORUM_SETSTATE; ++ ++ iov[0].iov_base = (char *)&req_lib_votequorum_general; ++ iov[0].iov_len = sizeof (struct req_lib_votequorum_general); ++ ++ error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1, ++ &res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status)); ++ ++ pthread_mutex_unlock (&votequorum_inst->response_mutex); ++ ++ if (error != CS_OK) { ++ goto error_exit; ++ } ++ ++ error = res_lib_votequorum_status.header.error; ++ ++error_exit: ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (error); ++} ++ ++cs_error_t votequorum_leaving ( ++ votequorum_handle_t handle) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ struct iovec iov[2]; ++ struct req_lib_votequorum_general req_lib_votequorum_general; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ pthread_mutex_lock (&votequorum_inst->response_mutex); ++ ++ req_lib_votequorum_general.header.size = sizeof (struct req_lib_votequorum_general); ++ req_lib_votequorum_general.header.id = MESSAGE_REQ_VOTEQUORUM_LEAVING; ++ ++ iov[0].iov_base = (char *)&req_lib_votequorum_general; ++ iov[0].iov_len = sizeof (struct req_lib_votequorum_general); ++ ++ error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1, ++ &res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status)); ++ ++ pthread_mutex_unlock (&votequorum_inst->response_mutex); ++ ++ if (error != CS_OK) { ++ goto error_exit; ++ } ++ ++ error = res_lib_votequorum_status.header.error; ++ ++error_exit: ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (error); ++} ++ ++cs_error_t votequorum_trackstart ( ++ votequorum_handle_t handle, ++ uint64_t context, ++ unsigned int flags ) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ struct iovec iov[2]; ++ struct req_lib_votequorum_trackstart req_lib_votequorum_trackstart; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ pthread_mutex_lock (&votequorum_inst->response_mutex); ++ ++ req_lib_votequorum_trackstart.header.size = sizeof (struct req_lib_votequorum_trackstart); ++ req_lib_votequorum_trackstart.header.id = MESSAGE_REQ_VOTEQUORUM_TRACKSTART; ++ req_lib_votequorum_trackstart.track_flags = flags; ++ req_lib_votequorum_trackstart.context = context; ++ ++ iov[0].iov_base = (char *)&req_lib_votequorum_trackstart; ++ iov[0].iov_len = sizeof (struct req_lib_votequorum_trackstart); ++ ++ error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1, ++ &res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status)); ++ ++ pthread_mutex_unlock (&votequorum_inst->response_mutex); ++ ++ if (error != CS_OK) { ++ goto error_exit; ++ } ++ ++ error = res_lib_votequorum_status.header.error; ++ ++error_exit: ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (error); ++} ++ ++cs_error_t votequorum_trackstop ( ++ votequorum_handle_t handle) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ struct iovec iov[2]; ++ struct req_lib_votequorum_general req_lib_votequorum_general; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ pthread_mutex_lock (&votequorum_inst->response_mutex); ++ ++ req_lib_votequorum_general.header.size = sizeof (struct req_lib_votequorum_general); ++ req_lib_votequorum_general.header.id = MESSAGE_REQ_VOTEQUORUM_TRACKSTOP; ++ ++ iov[0].iov_base = (char *)&req_lib_votequorum_general; ++ iov[0].iov_len = sizeof (struct req_lib_votequorum_general); ++ ++ error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1, ++ &res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status)); ++ ++ pthread_mutex_unlock (&votequorum_inst->response_mutex); ++ ++ if (error != CS_OK) { ++ goto error_exit; ++ } ++ ++ error = res_lib_votequorum_status.header.error; ++ ++error_exit: ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (error); ++} ++ ++ ++cs_error_t votequorum_context_get ( ++ votequorum_handle_t handle, ++ void **context) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ *context = votequorum_inst->context; ++ ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (CS_OK); ++} ++ ++cs_error_t votequorum_context_set ( ++ votequorum_handle_t handle, ++ void *context) ++{ ++ cs_error_t error; ++ struct votequorum_inst *votequorum_inst; ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ votequorum_inst->context = context; ++ ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ ++ return (CS_OK); ++} ++ ++ ++struct res_overlay { ++ mar_res_header_t header __attribute__((aligned(8))); ++ char data[512000]; ++}; ++ ++cs_error_t votequorum_dispatch ( ++ votequorum_handle_t handle, ++ cs_dispatch_flags_t dispatch_types) ++{ ++ struct pollfd ufds; ++ int timeout = -1; ++ cs_error_t error; ++ int cont = 1; /* always continue do loop except when set to 0 */ ++ int dispatch_avail; ++ struct votequorum_inst *votequorum_inst; ++ votequorum_callbacks_t callbacks; ++ struct res_overlay dispatch_data; ++ struct res_lib_votequorum_notification *res_lib_votequorum_notification; ++ ++ if (dispatch_types != CS_DISPATCH_ONE && ++ dispatch_types != CS_DISPATCH_ALL && ++ dispatch_types != CS_DISPATCH_BLOCKING) { ++ ++ return (CS_ERR_INVALID_PARAM); ++ } ++ ++ error = saHandleInstanceGet (&votequorum_handle_t_db, handle, ++ (void *)&votequorum_inst); ++ if (error != CS_OK) { ++ return (error); ++ } ++ ++ /* ++ * Timeout instantly for CS_DISPATCH_ONE or CS_DISPATCH_ALL and ++ * wait indefinately for CS_DISPATCH_BLOCKING ++ */ ++ if (dispatch_types == CS_DISPATCH_ALL) { ++ timeout = 0; ++ } ++ ++ do { ++ ufds.fd = votequorum_inst->dispatch_fd; ++ ufds.events = POLLIN; ++ ufds.revents = 0; ++ ++ pthread_mutex_lock (&votequorum_inst->dispatch_mutex); ++ ++ error = saPollRetry (&ufds, 1, timeout); ++ if (error != CS_OK) { ++ goto error_unlock; ++ } ++ ++ /* ++ * Handle has been finalized in another thread ++ */ ++ if (votequorum_inst->finalize == 1) { ++ error = CS_OK; ++ goto error_unlock; ++ } ++ ++ if ((ufds.revents & (POLLERR|POLLHUP|POLLNVAL)) != 0) { ++ error = CS_ERR_BAD_HANDLE; ++ goto error_unlock; ++ } ++ ++ dispatch_avail = ufds.revents & POLLIN; ++ if (dispatch_avail == 0 && dispatch_types == CS_DISPATCH_ALL) { ++ pthread_mutex_unlock (&votequorum_inst->dispatch_mutex); ++ break; /* exit do while cont is 1 loop */ ++ } else ++ if (dispatch_avail == 0) { ++ pthread_mutex_unlock (&votequorum_inst->dispatch_mutex); ++ continue; /* next poll */ ++ } ++ ++ if (ufds.revents & POLLIN) { ++ error = saRecvRetry (votequorum_inst->dispatch_fd, &dispatch_data.header, ++ sizeof (mar_res_header_t)); ++ if (error != CS_OK) { ++ goto error_unlock; ++ } ++ if (dispatch_data.header.size > sizeof (mar_res_header_t)) { ++ error = saRecvRetry (votequorum_inst->dispatch_fd, &dispatch_data.data, ++ dispatch_data.header.size - sizeof (mar_res_header_t)); ++ if (error != CS_OK) { ++ goto error_unlock; ++ } ++ } ++ } else { ++ pthread_mutex_unlock (&votequorum_inst->dispatch_mutex); ++ continue; ++ } ++ ++ /* ++ * Make copy of callbacks, message data, unlock instance, and call callback ++ * A risk of this dispatch method is that the callback routines may ++ * operate at the same time that votequorum_finalize has been called in another thread. ++ */ ++ memcpy (&callbacks, &votequorum_inst->callbacks, sizeof (votequorum_callbacks_t)); ++ pthread_mutex_unlock (&votequorum_inst->dispatch_mutex); ++ ++ /* ++ * Dispatch incoming message ++ */ ++ switch (dispatch_data.header.id) { ++ ++ case MESSAGE_RES_VOTEQUORUM_NOTIFICATION: ++ if (callbacks.votequorum_notify_fn == NULL) { ++ continue; ++ } ++ res_lib_votequorum_notification = (struct res_lib_votequorum_notification *)&dispatch_data; ++ ++ callbacks.votequorum_notify_fn ( handle, ++ res_lib_votequorum_notification->context, ++ res_lib_votequorum_notification->quorate, ++ res_lib_votequorum_notification->node_list_entries, ++ (votequorum_node_t *)res_lib_votequorum_notification->node_list ); ++ ; ++ break; ++ ++ default: ++ error = CS_ERR_LIBRARY; ++ goto error_put; ++ break; ++ } ++ ++ /* ++ * Determine if more messages should be processed ++ * */ ++ switch (dispatch_types) { ++ case CS_DISPATCH_ONE: ++ cont = 0; ++ break; ++ case CS_DISPATCH_ALL: ++ break; ++ case CS_DISPATCH_BLOCKING: ++ break; ++ } ++ } while (cont); ++ ++ goto error_put; ++ ++error_unlock: ++ pthread_mutex_unlock (&votequorum_inst->dispatch_mutex); ++ ++error_put: ++ saHandleInstancePut (&votequorum_handle_t_db, handle); ++ return (error); ++} diff -Naurd corosync-0.92/Makefile corosync-trunk/Makefile --- corosync-0.92/Makefile 2008-09-03 09:58:08.000000000 +0200 -+++ corosync-trunk/Makefile 2008-12-11 10:42:17.000000000 +0100 ++++ corosync-trunk/Makefile 2009-01-26 11:46:08.000000000 +0100 @@ -115,10 +115,17 @@ (cd $(builddir)test; echo ==== `pwd` ===; $(call sub_make,test,clean)); rm -rf $(builddir)doc/api +-COROSYNC_LIBS = evs cpg cfg coroutil confdb +lint: + (cd $(builddir)exec; echo ==== `pwd` ===; $(call sub_make,exec,lint)); + (cd $(builddir)services; echo ==== `pwd` ===; $(call sub_make,services,lint)); @@ -12219,14 +14751,41 @@ diff -Naurd corosync-0.92/Makefile corosync-trunk/Makefile + (cd $(builddir)lib; echo ==== `pwd` ===; $(call sub_make,lib,lint)); + (cd $(builddir)tools; echo ==== `pwd` ===; $(call sub_make,tools,lint)); + - COROSYNC_LIBS = evs cpg cfg coroutil confdb ++COROSYNC_LIBS = evs cpg cfg coroutil confdb quorum votequorum COROSYNC_HEADERS = cpg.h cfg.h evs.h ipc_gen.h mar_gen.h swab.h \ - ais_util.h confdb.h list.h saAis.h -+ ais_util.h confdb.h list.h corotypes.h ++ ais_util.h confdb.h quorum.h list.h corotypes.h votequorum.h EXEC_LIBS = totem_pg logsys +@@ -145,7 +152,7 @@ + install -m 755 exec/lib$$eLib.so.2.* $(DESTDIR)$(LIBDIR); \ + if [ "xYES" = "x$(STATICLIBS)" ]; then \ + install -m 755 exec/lib$$eLib.a $(DESTDIR)$(LIBDIR); \ +- if [ ${OPENCOROSYNC_COMPAT} = "DARWIN" ]; then \ ++ if [ ${COROSYNC_COMPAT} = "DARWIN" ]; then \ + ranlib $(DESTDIR)$(LIBDIR)/lib$$eLib.a; \ + fi \ + fi \ +@@ -161,7 +168,7 @@ + install -m 755 lib/lib$$aLib.so.2.* $(DESTDIR)$(LIBDIR); \ + if [ "xYES" = "x$(STATICLIBS)" ]; then \ + install -m 755 lib/lib$$aLib.a $(DESTDIR)$(LIBDIR); \ +- if [ ${OPENCOROSYNC_COMPAT} = "DARWIN" ]; then \ ++ if [ ${COROSYNC_COMPAT} = "DARWIN" ]; then \ + ranlib $(DESTDIR)$(LIBDIR)/lib$$aLib.a; \ + fi \ + fi \ +@@ -177,7 +184,7 @@ + install -m 755 $(builddir)tools/corosync-cfgtool $(DESTDIR)$(SBINDIR) + install -m 755 $(builddir)tools/corosync-keygen $(DESTDIR)$(SBINDIR) + +- if [ ! -f $(DESTDIR)$(ETCDIR)/penais.conf ] ; then \ ++ if [ ! -f $(DESTDIR)$(ETCDIR)/corosync.conf ] ; then \ + install -m 644 $(srcdir)conf/corosync.conf $(DESTDIR)$(ETCDIR) ; \ + fi + @@ -196,6 +203,7 @@ install -m 644 $(srcdir)include/corosync/engine/coroapi.h $(DESTDIR)$(INCLUDEDIR_ENGINE) install -m 644 $(srcdir)include/corosync/engine/objdb.h $(DESTDIR)$(INCLUDEDIR_ENGINE) @@ -12300,6 +14859,35 @@ diff -Naurd corosync-0.92/Makefile.inc corosync-trunk/Makefile.inc override LDFLAGS += -ldl -lpthread override DYFLAGS += -rdynamic endif +diff -Naurd corosync-0.92/man/confdb_overview.8 corosync-trunk/man/confdb_overview.8 +--- corosync-0.92/man/confdb_overview.8 2008-08-15 08:15:26.000000000 +0200 ++++ corosync-trunk/man/confdb_overview.8 2009-01-26 11:46:08.000000000 +0100 +@@ -34,16 +34,24 @@ + .TH CONFDB_OVERVIEW 8 2006-03-06 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" + .SH OVERVIEW + The CONFDB library is delivered with the corosync project. This library is used +-to examine manipulate the configuratin databser used by corosync. ++to examine manipulate the configuration database used by corosync. + .PP + The library provides a mechanism to: ++.PP + * Create new objects ++.PP + * Create new key/value pairs within those objects ++.PP + * Remove existing keys ++.PP + * Remove an existing object and all it sub-objects and keys ++.PP + * Read keys and values ++.PP + * Iterate keys within an object ++.PP + * Iterate subobjects within a parent object ++.PP + * Find a named object + .PP + .SH BUGS diff -Naurd corosync-0.92/man/corosync.conf.5 corosync-trunk/man/corosync.conf.5 --- corosync-0.92/man/corosync.conf.5 2008-08-15 08:15:26.000000000 +0200 +++ corosync-trunk/man/corosync.conf.5 2008-10-21 00:05:51.000000000 +0200 @@ -12324,10 +14912,1087 @@ diff -Naurd corosync-0.92/man/corosync.conf.5 corosync-trunk/man/corosync.conf.5 timestamp This specifies that a timestamp is placed on all log messages. +diff -Naurd corosync-0.92/man/index.html corosync-trunk/man/index.html +--- corosync-0.92/man/index.html 2008-08-14 18:54:46.000000000 +0200 ++++ corosync-trunk/man/index.html 2009-01-26 11:46:08.000000000 +0100 +@@ -85,5 +85,30 @@ +
+ confdb_object_parent_get(3): Description of the confdb_object_parent_get interface. + ++
++votequorum_overview(8): An overview of the vote-based quorum service ++
++votequorum_initialize(3): Description of the votequorum interface. ++
++votequorum_finalize(3): Description of the votequorum interface. ++
++votequorum_fd_get(3): Description of the votequorum interface. ++
++votequorum_getinfo(3): Description of the votequorum interface. ++
++votequorum_leaving(3): Description of the votequorum interface. ++
++votequorum_setexpected(3): Description of the votequorum interface. ++
++votequorum_setvotes(3): Description of the votequorum interface. ++
++votequorum_qdisk_register(3): Description of the votequorum interface. ++
++votequorum_qdisk_unregister(3): Description of the votequorum interface. ++
++votequorum_qdisk_poll(3): Description of the votequorum interface. ++
++votequorum_qdisk_getinfo(3): Description of the votequorum interface. ++
+ + +diff -Naurd corosync-0.92/man/Makefile corosync-trunk/man/Makefile +--- corosync-0.92/man/Makefile 2008-08-14 18:54:46.000000000 +0200 ++++ corosync-trunk/man/Makefile 2009-01-26 11:46:08.000000000 +0100 +@@ -74,6 +74,19 @@ + groff -mandoc -Thtml confdb_object_parent_get.3 > html/confdb_object_parent_get.html + groff -mandoc -Thtml confdb_overview.8 > html/confdb_overview.html + ++ groff -mandoc -Thtml votequorum_overview.8 > html/votequorum_overview.html ++ groff -mandoc -Thtml votequorum_initialize.3 > html/votequorum_initialize.html ++ groff -mandoc -Thtml votequorum_finalize.3 > html/votequorum_finalize.html ++ groff -mandoc -Thtml votequorum_fd_get.3 > html/votequorum_fd_get.html ++ groff -mandoc -Thtml votequorum_dispatch.3 > html/votequorum_dispatch.html ++ groff -mandoc -Thtml votequorum_getinfo.3 > html/votequorum_getinfo.html ++ groff -mandoc -Thtml votequorum_leaving.3 > html/votequorum_leaving.html ++ groff -mandoc -Thtml votequorum_setexpected.3 > html/votequorum_setexpected.html ++ groff -mandoc -Thtml votequorum_setvotes.3 > html/votequorum_setvotes.html ++ groff -mandoc -Thtml votequorum_qdisk_register.3 > html/votequorum_qdisk_register.html ++ groff -mandoc -Thtml votequorum_qdisk_unregister.3 > html/votequorum_qdisk_unregister.html ++ groff -mandoc -Thtml votequorum_qdisk_poll.3 > html/votequorum_poll.html ++ groff -mandoc -Thtml votequorum_qdisk_getinfo.3 > html/votequorum_qdisk_getinfo.html + cp index.html html + + clean: +diff -Naurd corosync-0.92/man/votequorum_dispatch.3 corosync-trunk/man/votequorum_dispatch.3 +--- corosync-0.92/man/votequorum_dispatch.3 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/man/votequorum_dispatch.3 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,96 @@ ++.\"/* ++.\" * Copyright (c) 2009 Red Hat, Inc. ++.\" * ++.\" * All rights reserved. ++.\" * ++.\" * Author: Christine Caulfield ++.\" * ++.\" * 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. ++.\" */ ++.TH VOTEQUORUM_DISPATCH 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" ++.SH NAME ++votequorum_dispatch \- Dispatches callbacks from the votequorum service ++.SH SYNOPSIS ++.B #include ++.sp ++.BI "int votequorum_dispatch(votequorum_handle_t " handle ", votequorum_dispatch_t *" dispatch_types ");" ++.SH DESCRIPTION ++The ++.B votequorum_dispatch ++function is used to dispatch configuration changes. ++.PP ++Each application may have several connections to the votequorum API. Each application ++uses the ++.I handle ++argument to uniquely identify the connection. ++.PP ++The ++.I dispatch_types ++argument is used to identify the type of dispatch to execute. The possible types are ++defined by the structure: ++ ++.IP ++.RS ++.ne 18 ++.nf ++.ta 4n 30n 33n ++typedef enum { ++ CS_DISPATCH_ONE, ++ CS_DISPATCH_ALL, ++ CS_DISPATCH_BLOCKING ++} votequorum_dispatch_t; ++.ta ++.fi ++.RE ++.IP ++.PP ++.PP ++The dispatch values have the following meanings: ++.TP ++.B CS_DISPATCH_ONE ++Dispatch at least one callback, blocking until the callback is dispatched. ++.TP ++.B CS_DISPATCH_ALL ++Dispatch all waiting callbacks without blocking to wait for any callbacks. ++.TP ++.B CS_DISPATCH_BLOCKING ++Dispatch all callbacks blocking indefinitely. This is used in a threaded ++program where a thread is created, and then votequorum_dispatch() is called immediately ++from the created thread to execute callbacks. ++ ++.SH RETURN VALUE ++This call returns the CS_OK value if successful, otherwise an error is returned. ++.PP ++.SH ERRORS ++The errors are undocumented. ++.SH "SEE ALSO" ++.BR votequorum_overview (8), ++.BR votequorum_initialize (3), ++.BR votequorum_finalize (3), ++.BR votequorum_fd_get (3), ++ ++.PP +diff -Naurd corosync-0.92/man/votequorum_fd_get.3 corosync-trunk/man/votequorum_fd_get.3 +--- corosync-0.92/man/votequorum_fd_get.3 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/man/votequorum_fd_get.3 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,64 @@ ++.\"/* ++.\" * Copyright (c) 2009 Red Hat, Inc. ++.\" * ++.\" * All rights reserved. ++.\" * ++.\" * Author: Christine Caulfield ++.\" * ++.\" * 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. ++.\" */ ++.TH VOTEQUORUM_FD_GET 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" ++.SH NAME ++votequorum_fd_get \- Dispatches callbacks from the votequorum service ++.SH SYNOPSIS ++.B #include ++.sp ++.BI "int votequorum_fd_get(votequorum_handle_t " handle ", int *" fd ");" ++.SH DESCRIPTION ++The ++.B votequorum_fd_get ++function is used to retrieve the file descriptor that may be used with the poll ++system call to determine when ++.B votequorum_dispatch(3) ++won't block. The ++.I handle ++argument may not be used directly with ++.B poll ++because it is not the file descriptor, but instead an internal identifier used ++by the votequorum library. ++.SH RETURN VALUE ++This call returns the CS_OK value if successful, otherwise an error is returned. ++.PP ++.SH ERRORS ++The errors are undocumented. ++.SH "SEE ALSO" ++.BR votequorum_overview (8), ++.BR votequorum_initialize (3), ++.BR votequorum_finalize (3), ++.BR votequorum_dispatch (3), ++.BR votequorum_fd_get (3), ++.PP +diff -Naurd corosync-0.92/man/votequorum_finalize.3 corosync-trunk/man/votequorum_finalize.3 +--- corosync-0.92/man/votequorum_finalize.3 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/man/votequorum_finalize.3 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,61 @@ ++.\"/* ++.\" * Copyright (c) 2009 Red Hat, Inc. ++.\" * ++.\" * All rights reserved. ++.\" * ++.\" * Author: Christine Caulfield ++.\" * ++.\" * 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. ++.\" */ ++.TH VOTEQUORUM_FINALIZE 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" ++.SH NAME ++votequorum_finalize \- Terminate a connection to the votequorum service ++.SH SYNOPSIS ++.B #include ++.sp ++.BI "int votequorum_finalize(votequorum_handle_t " handle ");" ++.SH DESCRIPTION ++The ++.B votequorum_finalize ++function is used to close a connection to the configuration dabatase API. ++Once the connection is finalized, the handle may not be used again by applications. ++No more callbacks will be dispatched from the ++.B votequorum_dispatch function. ++.PP ++.SH RETURN VALUE ++This call returns the CS_OK value if successful, otherwise an error is returned. ++.PP ++.SH ERRORS ++The errors are undocumented. ++.SH "SEE ALSO" ++.BR votequorum_overview (8), ++.BR votequorum_initialize (3), ++.BR votequorum_finalize (3), ++.BR votequorum_dispatch (3), ++.BR votequorum_fd_get (3), ++ ++.PP +diff -Naurd corosync-0.92/man/votequorum_getinfo.3 corosync-trunk/man/votequorum_getinfo.3 +--- corosync-0.92/man/votequorum_getinfo.3 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/man/votequorum_getinfo.3 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,91 @@ ++.\"/* ++.\" * Copyright (c) 2009 Red Hat, Inc. ++.\" * ++.\" * All rights reserved. ++.\" * ++.\" * Author: Christine Caulfield ++.\" * ++.\" * 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. ++.\" */ ++.TH VOTEQUORUM_GETINFO 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" ++.SH NAME ++votequorum_getinfo \- Get information about the VoteQuorum service ++.SH SYNOPSIS ++.B #include ++.sp ++.BI "int votequorum_getinfo(votequorum_handle_t *" handle ", unsigned int " nodeid ", struct votequorum_info *" info "); ++.SH DESCRIPTION ++The ++.B votequorum_getinfo ++function is used to get information about the voteing system and its nodes. ++ ++The votequorum_info structure is defined as follows: ++.PP ++.PP ++.IP ++.RS ++.ne 18 ++.nf ++.ta 4n 20n 32n ++ ++struct votequorum_info { ++ unsigned int node_id; ++ unsigned int node_votes; ++ unsigned int node_expected_votes; ++ unsigned int highest_expected; ++ unsigned int total_votes; ++ unsigned int quorum; ++ unsigned int flags; ++}; ++ ++#define VOTEQUORUM_INFO_FLAG_DIRTY 1 ++#define VOTEQUORUM_INFO_FLAG_DISALLOWED 2 ++#define VOTEQUORUM_INFO_FLAG_TWONODE 4 ++#define VOTEQUORUM_INFO_FLAG_QUORATE 8 ++ ++.ta ++.fi ++.RE ++.IP ++.PP ++.PP ++The members starting node_ hold information specific to the requested nodeid, the other are ++general to the voting system. ++.SH RETURN VALUE ++This call returns the CS_OK value if successful, otherwise an error is returned. ++.PP ++.SH BUGS ++Callbacks are not support at the moment. ++.PP ++.SH ERRORS ++The errors are undocumented. ++.SH "SEE ALSO" ++.BR votequorum_overview (8), ++.BR votequorum_finalize (3), ++.BR votequorum_fd_get (3), ++.BR votequorum_dispatch (3), ++.PP +diff -Naurd corosync-0.92/man/votequorum_initialize.3 corosync-trunk/man/votequorum_initialize.3 +--- corosync-0.92/man/votequorum_initialize.3 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/man/votequorum_initialize.3 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,106 @@ ++.\"/* ++.\" * Copyright (c) 2009 Red Hat, Inc. ++.\" * ++.\" * All rights reserved. ++.\" * ++.\" * Author: Christine Caulfield ++.\" * ++.\" * 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. ++.\" */ ++.TH VOTEQUORUM_INITIALIZE 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" ++.SH NAME ++votequorum_initialize \- Create a new connection to the VoteQuorum service ++.SH SYNOPSIS ++.B #include ++.sp ++.BI "int votequorum_initialize(votequorum_handle_t *" handle ", votequorum_callbacks_t *" callbacks "); ++.SH DESCRIPTION ++The ++.B votequorum_initialize ++function is used to initialize a connection to the vote-based quorum database API. ++.PP ++Each application may have several connections to the votequorum API. Each application ++uses the ++.I handle ++argument to uniquely identify the connection. The ++.I handle ++argument is then used in other function calls to identify the connection to be used ++for communication with the votequorum service. ++.PP ++Every time the voting configuraton changes (eg a node joins or leave the cluster), the callback is called. ++The callback function is described by the following type definitions: ++ ++typedef void (*votequorum_notification_fn_t) ( ++ votequorum_handle_t handle, ++ uint64_t context, ++ uint32_t quorate, ++ uint32_t node_list_entries, ++ votequorum_node_t node_list[] ++ ); ++ ++.ta ++.fi ++.RE ++.IP ++.PP ++.PP ++The ++.I callbacks ++argument is of the type: ++.IP ++.RS ++.ne 18 ++.nf ++.PP ++typedef struct { ++ votequorum_notification_fn_t votequorum_notify_fn; ++} votequorum_callbacks_t; ++ ++.ta ++.fi ++.RE ++.IP ++.PP ++When a configuration change occurs, the callback ++is called from the ++.B votequorum_dispatch() ++function. ++.PP ++.SH RETURN VALUE ++This call returns the CS_OK value if successful, otherwise an error is returned. ++.PP ++.SH BUGS ++Callbacks are not support at the moment. ++.PP ++.SH ERRORS ++The errors are undocumented. ++.SH "SEE ALSO" ++.BR votequorum_overview (8), ++.BR votequorum_finalize (3), ++.BR votequorum_fd_get (3), ++.BR votequorum_dispatch (3), ++.PP +diff -Naurd corosync-0.92/man/votequorum_leaving.3 corosync-trunk/man/votequorum_leaving.3 +--- corosync-0.92/man/votequorum_leaving.3 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/man/votequorum_leaving.3 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,67 @@ ++.\"/* ++.\" * Copyright (c) 2009 Red Hat, Inc. ++.\" * ++.\" * All rights reserved. ++.\" * ++.\" * Author: Christine Caulfield ++.\" * ++.\" * 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. ++.\" */ ++.TH VOTEQUORUM_LEAVING 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" ++.SH NAME ++votequorum_leaving \- Tell other nodes that we are leaving the cluster ++.SH SYNOPSIS ++.B #include ++.sp ++.BI "int votequorum_leaving(votequorum_handle_t " handle ");" ++.SH DESCRIPTION ++The ++.B votequorum_leaving ++function is used to tell the other nodes in the cluster that this node is leaving. They ++will (when the node actually leaves) reduce quorum to keep the cluster running without ++this node. ++.PP ++This function should only be called if it is known that the node is being shut down for ++a known reason and could be out of the cluster for an extended period of time. ++.PP ++Normal behaviour is for the cluster to reduce the total number of votes, but NOT expected_votes ++when a node leave the cluster, so the cluster could become inquorate. This is correct behaviour ++and is ther eto prevent split-brain. ++.PP ++Do NOT call this function unless you know what you are doing. ++.SH RETURN VALUE ++This call returns the CS_OK value if successful, otherwise an error is returned. ++.PP ++.SH ERRORS ++The errors are undocumented. ++.SH "SEE ALSO" ++.BR votequorum_overview (8), ++.BR votequorum_initialize (3), ++.BR votequorum_finalize (3), ++.BR votequorum_dispatch (3), ++.BR votequorum_fd_get (3), ++.PP +diff -Naurd corosync-0.92/man/votequorum_overview.8 corosync-trunk/man/votequorum_overview.8 +--- corosync-0.92/man/votequorum_overview.8 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/man/votequorum_overview.8 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,82 @@ ++.\"/* ++.\" * Copyright (c) 2008 Red Hat, Inc. ++.\" * ++.\" * All rights reserved. ++.\" * ++.\" * Author: Christine Caulfield ++.\" * ++.\" * 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. ++.\" */ ++.TH VOTEQUORUM_OVERVIEW 8 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" ++.SH OVERVIEW ++The votequuorum library is delivered with the corosync project. It is the external interface to ++the vote-based quorum service. This service is optionally loaded into all ndes in a corosync cluster ++to avoid split-brain situations. It does this by having a number of votes assigned to each system ++in the cluster and ensuring that only when a majority of the votes are present, cluster operations are ++allowed to proceed. ++.PP ++The library provides a mechanism to: ++* Query the quorum status ++.PP ++* Get a list of nodes known to the quorum service ++.PP ++* Receive notifications of quorum state changes ++.PP ++* Change the number of votes assigned to a node ++.PP ++* Change the number of expected votes for a cluster to be quorate ++.PP ++* Connect an additional quorum device to allow small clusters to remain quorate during node outages. ++.PP ++.B votequorum ++reads its configuration from the objdb. The following keys are read when it starts up: ++.PP ++* quorum.expected_votes ++.br ++* quorum.votes ++.br ++* quorum.quorumdev_poll ++.br ++* quorum.disallowed ++.br ++* quorum.two_node ++.PP ++Most of those values can be changed while corosync is running with the following exceptions: ++.B quorum.disallowed ++cannot be changed, and ++.B two_node ++cannot be set on-the-fly, though it can be cleared. ie you can start with two nodes in the cluster ++and add a third without rebooting all the nodes. ++.PP ++.SH BUGS ++This software is not yet production, so there may still be some bugs. ++.SH "SEE ALSO" ++.BR votequorum_initialize (3), ++.BR votequorum_finalize (3), ++.BR votequorum_fd_get (3), ++.BR votequorum_dispatch (3), ++.PP +diff -Naurd corosync-0.92/man/votequorum_qdisk_getinfo.3 corosync-trunk/man/votequorum_qdisk_getinfo.3 +--- corosync-0.92/man/votequorum_qdisk_getinfo.3 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/man/votequorum_qdisk_getinfo.3 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,80 @@ ++.\"/* ++.\" * Copyright (c) 2009 Red Hat, Inc. ++.\" * ++.\" * All rights reserved. ++.\" * ++.\" * Author: Christine Caulfield ++.\" * ++.\" * 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. ++.\" */ ++.TH VOTEQUORUM_QDISK_GETINFO 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" ++.SH NAME ++votequorum_qdisk_getinfo \- Get details of the quorum device ++.SH SYNOPSIS ++.B #include ++.sp ++.BI "int votequorum_qdisk_getinfo(votequorum_handle_t " handle ", struct votequorum_qdisk_info " *info ");" ++.SH DESCRIPTION ++The ++.B votequorum_qdisk_getinfo ++Returns information about the quorum device in the following structure: ++.PP ++.PP ++.IP ++.RS ++.ne 18 ++.nf ++.ta 4n 20n 32n ++ ++struct votequorum_qdisk_info { ++ unsigned int votes; ++ unsigned int state; ++ char name[VOTEQUORUM_MAX_QDISK_NAME_LEN]; ++}; ++ ++.ta ++.fi ++.RE ++.IP ++.PP ++.PP ++ ++.SH RETURN VALUE ++This call returns the CS_OK value if successful, otherwise an error is returned. ++.PP ++.SH ERRORS ++The errors are undocumented. ++.SH "SEE ALSO" ++.BR votequorum_overview (8), ++.BR votequorum_initialize (3), ++.BR votequorum_finalize (3), ++.BR votequorum_dispatch (3), ++.BR votequorum_fd_get (3), ++.BR votequorum_qdisk_poll (3), ++.BR votequorum_qdisk_unregister (3), ++.BR votequorum_qdisk_getinfo (3), ++.PP +diff -Naurd corosync-0.92/man/votequorum_qdisk_poll.3 corosync-trunk/man/votequorum_qdisk_poll.3 +--- corosync-0.92/man/votequorum_qdisk_poll.3 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/man/votequorum_qdisk_poll.3 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,69 @@ ++.\"/* ++.\" * Copyright (c) 2009 Red Hat, Inc. ++.\" * ++.\" * All rights reserved. ++.\" * ++.\" * Author: Christine Caulfield ++.\" * ++.\" * 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. ++.\" */ ++.TH VOTEQUORUM_QDISK_POLL 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" ++.SH NAME ++votequorum_qdisk_poll \- Tells votequorum the result of the quorum device poll ++.SH SYNOPSIS ++.B #include ++.sp ++.BI "int votequorum_qdisk_poll(votequorum_handle_t " handle ", unsigned int " state ");" ++.SH DESCRIPTION ++The ++.B votequorum_qdisk_poll ++is called by the quorum device subsyetem (not provided as part of votequorum) to tell ++the voting system if the qurum device is present/active or not. If ++.B state ++is 1 then the votes for the device are included in the quorum calculation, otherwise not. ++This routine should be called at regular intervals to ensure that the device status ++is always known to votequorum. If ++.B votequorum_qdisk_poll ++is not called after (default) 10 seconds then the device will be deeded to be dead and ++its votes removed from the cluster. This does not unregister the device. ++The default poll time can be changed by setting the object database variable ++quorum.quorumdev_poll. ++.SH RETURN VALUE ++This call returns the CS_OK value if successful, otherwise an error is returned. ++.PP ++.SH ERRORS ++The errors are undocumented. ++.SH "SEE ALSO" ++.BR votequorum_overview (8), ++.BR votequorum_initialize (3), ++.BR votequorum_finalize (3), ++.BR votequorum_dispatch (3), ++.BR votequorum_fd_get (3), ++.BR votequorum_qdisk_poll (3), ++.BR votequorum_qdisk_unregister (3), ++.BR votequorum_qdisk_getinfo (3), ++.PP +diff -Naurd corosync-0.92/man/votequorum_qdisk_register.3 corosync-trunk/man/votequorum_qdisk_register.3 +--- corosync-0.92/man/votequorum_qdisk_register.3 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/man/votequorum_qdisk_register.3 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,68 @@ ++.\"/* ++.\" * Copyright (c) 2009 Red Hat, Inc. ++.\" * ++.\" * All rights reserved. ++.\" * ++.\" * Author: Christine Caulfield ++.\" * ++.\" * 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. ++.\" */ ++.TH VOTEQUORUM_QDISK_REGISTER 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" ++.SH NAME ++votequorum_qdisk_register \- Registers a new quorum device ++.SH SYNOPSIS ++.B #include ++.sp ++.BI "int votequorum_qdisk_register(votequorum_handle_t " handle ", char * " name ", unsigned int " votes ");" ++.SH DESCRIPTION ++The ++.B votequorum_qdisk_register ++is used to register a new quorum device. A quorum device is an external way of adding votes to a small ++cluster. The quorum device is, in effect, a pseudo node in the cluster that provide votes based on some ++external device, usually a shared disk partition or perhaps a network router. ++.br ++This call creates the device but does not mark it active. ++.B votequorum_qdisk_poll ++must be called for the votes to be included in the quorum calculation. ++.br ++Note that it is the responsibility of the quorum device subsystem (not provided as part of votequorum) ++to keep all nodes informed of the quorum device status. ++.SH RETURN VALUE ++This call returns the CS_OK value if successful, otherwise an error is returned. ++.PP ++.SH ERRORS ++The errors are undocumented. ++.SH "SEE ALSO" ++.BR votequorum_overview (8), ++.BR votequorum_initialize (3), ++.BR votequorum_finalize (3), ++.BR votequorum_dispatch (3), ++.BR votequorum_fd_get (3), ++.BR votequorum_qdisk_poll (3), ++.BR votequorum_qdisk_unregister (3), ++.BR votequorum_qdisk_getinfo (3), ++.PP +diff -Naurd corosync-0.92/man/votequorum_qdisk_unregister.3 corosync-trunk/man/votequorum_qdisk_unregister.3 +--- corosync-0.92/man/votequorum_qdisk_unregister.3 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/man/votequorum_qdisk_unregister.3 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,60 @@ ++.\"/* ++.\" * Copyright (c) 2009 Red Hat, Inc. ++.\" * ++.\" * All rights reserved. ++.\" * ++.\" * Author: Christine Caulfield ++.\" * ++.\" * 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. ++.\" */ ++.TH VOTEQUORUM_QDISK_UNREGISTER 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" ++.SH NAME ++votequorum_qdisk_unregister \- Unregisters a new quorum device ++.SH SYNOPSIS ++.B #include ++.sp ++.BI "int votequorum_qdisk_unregister(votequorum_handle_t " handle ");" ++.SH DESCRIPTION ++The ++.B votequorum_qdisk_unregister ++unregisters a quorum device. Any votes it had will be removed from the cluster. Not that this could ++make the cluster inquorate. ++.SH RETURN VALUE ++This call returns the CS_OK value if successful, otherwise an error is returned. ++.PP ++.SH ERRORS ++The errors are undocumented. ++.SH "SEE ALSO" ++.BR votequorum_overview (8), ++.BR votequorum_initialize (3), ++.BR votequorum_finalize (3), ++.BR votequorum_dispatch (3), ++.BR votequorum_fd_get (3), ++.BR votequorum_qdisk_poll (3), ++.BR votequorum_qdisk_unregister (3), ++.BR votequorum_qdisk_getinfo (3), ++.PP +diff -Naurd corosync-0.92/man/votequorum_setexpected.3 corosync-trunk/man/votequorum_setexpected.3 +--- corosync-0.92/man/votequorum_setexpected.3 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/man/votequorum_setexpected.3 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,60 @@ ++.\"/* ++.\" * Copyright (c) 2009 Red Hat, Inc. ++.\" * ++.\" * All rights reserved. ++.\" * ++.\" * Author: Christine Caulfield ++.\" * ++.\" * 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. ++.\" */ ++.TH VOTEQUORUM_SETEXPECTED 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" ++.SH NAME ++votequorum_setexpected \- Sets the expected votes for the cluster ++.SH SYNOPSIS ++.B #include ++.sp ++.BI "int votequorum_setexpected(votequorum_handle_t " handle ", int " expected_votes ");" ++.SH DESCRIPTION ++The ++.B votequorum_setexpected ++function is used to change the expected votes in the cluster. Expected votes is used to calculate ++quorum and should normally be the total number of votes that will exist when all the expected nodes ++are joined. Quorum will usually be half of this (rounded up). ++.br ++It is not possible to set expected votes up so that it makes the cluster inquorate using this command. ++.SH RETURN VALUE ++This call returns the CS_OK value if successful, otherwise an error is returned. ++.PP ++.SH ERRORS ++The errors are undocumented. ++.SH "SEE ALSO" ++.BR votequorum_overview (8), ++.BR votequorum_initialize (3), ++.BR votequorum_finalize (3), ++.BR votequorum_dispatch (3), ++.BR votequorum_fd_get (3), ++.PP +diff -Naurd corosync-0.92/man/votequorum_setvotes.3 corosync-trunk/man/votequorum_setvotes.3 +--- corosync-0.92/man/votequorum_setvotes.3 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/man/votequorum_setvotes.3 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,57 @@ ++.\"/* ++.\" * Copyright (c) 2009 Red Hat, Inc. ++.\" * ++.\" * All rights reserved. ++.\" * ++.\" * Author: Christine Caulfield ++.\" * ++.\" * 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. ++.\" */ ++.TH VOTEQUORUM_VOTES 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual" ++.SH NAME ++votequorum_setvotes \- Sets the number of votes for a node ++.SH SYNOPSIS ++.B #include ++.sp ++.BI "int votequorum_setexpected(votequorum_handle_t " handle ", unsigned int " nodeid ", int " votes ");" ++.SH DESCRIPTION ++The ++.B votequorum_setvotes ++is used to change the number of votes that a node has. Note that it is not possible, using this function, ++to change the number of node votes such that the cluster goes inquorate. ++.SH RETURN VALUE ++This call returns the CS_OK value if successful, otherwise an error is returned. ++.PP ++.SH ERRORS ++The errors are undocumented. ++.SH "SEE ALSO" ++.BR votequorum_overview (8), ++.BR votequorum_initialize (3), ++.BR votequorum_finalize (3), ++.BR votequorum_dispatch (3), ++.BR votequorum_fd_get (3), ++.PP diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c --- corosync-0.92/services/cfg.c 2008-08-14 18:44:26.000000000 +0200 -+++ corosync-trunk/services/cfg.c 2008-11-06 22:49:07.000000000 +0100 -@@ -7,7 +7,7 @@ ++++ corosync-trunk/services/cfg.c 2009-01-19 09:31:21.000000000 +0100 +@@ -1,13 +1,13 @@ + /* + * Copyright (c) 2005-2006 MontaVista Software, Inc. +- * Copyright (c) 2006-2008 Red Hat, 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: @@ -12336,7 +16001,12 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * -@@ -46,7 +46,7 @@ +@@ -42,16 +42,18 @@ + #include + #include + #include ++#include + #include #include #include @@ -12345,7 +16015,13 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c #include #include #include -@@ -60,7 +60,31 @@ + #include + #include ++#include + #include + #include + #include +@@ -60,7 +62,31 @@ LOGSYS_DECLARE_SUBSYS ("CFG", LOG_INFO); enum cfg_message_req_types { @@ -12378,7 +16054,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c }; static void cfg_confchg_fn ( -@@ -82,6 +106,16 @@ +@@ -82,6 +108,16 @@ void *message, unsigned int nodeid); @@ -12395,7 +16071,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c static void message_handler_req_lib_cfg_ringstatusget ( void *conn, void *msg); -@@ -114,6 +148,18 @@ +@@ -114,6 +150,22 @@ void *conn, void *msg); @@ -12410,11 +16086,15 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c +static void message_handler_req_lib_cfg_replytoshutdown ( + void *conn, + void *msg); ++ ++static void message_handler_req_lib_cfg_get_node_addrs ( ++ void *conn, ++ void *msg); + /* * Service Handler Definition */ -@@ -123,56 +169,81 @@ +@@ -123,56 +175,87 @@ .lib_handler_fn = message_handler_req_lib_cfg_ringstatusget, .response_size = sizeof (struct res_lib_cfg_ringstatusget), .response_id = MESSAGE_RES_CFG_RINGSTATUSGET, @@ -12486,6 +16166,12 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c + .lib_handler_fn = message_handler_req_lib_cfg_replytoshutdown, + .response_size = 0, + .response_id = 0, ++ .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED ++ }, ++ { /* 11 */ ++ .lib_handler_fn = message_handler_req_lib_cfg_get_node_addrs, ++ .response_size = sizeof (struct res_lib_cfg_get_node_addrs), ++ .response_id = MESSAGE_RES_CFG_GET_NODE_ADDRS, + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED } }; @@ -12506,7 +16192,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c } }; -@@ -182,8 +253,9 @@ +@@ -182,8 +265,9 @@ struct corosync_service_engine cfg_service_engine = { .name = "corosync configuration service", .id = CFG_SERVICE, @@ -12518,7 +16204,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c .lib_init_fn = cfg_lib_init_fn, .lib_exit_fn = cfg_lib_exit_fn, .lib_engine = cfg_lib_engine, -@@ -238,12 +310,24 @@ +@@ -238,12 +322,24 @@ mar_message_source_t source __attribute__((aligned(8))); }; @@ -12543,7 +16229,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c return (0); } -@@ -256,16 +340,193 @@ +@@ -256,16 +352,193 @@ { } @@ -12740,7 +16426,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c return (0); } -@@ -281,18 +542,64 @@ +@@ -281,18 +554,64 @@ (struct req_exec_cfg_ringreenable *)message; struct res_lib_cfg_ringreenable res_lib_cfg_ringreenable; @@ -12808,7 +16494,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c } -@@ -310,11 +617,11 @@ +@@ -310,11 +629,11 @@ char *totem_ip_string; unsigned int i; @@ -12822,7 +16508,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c api->totem_ifaces_get ( api->totem_nodeid_get(), -@@ -336,7 +643,7 @@ +@@ -336,7 +655,7 @@ &res_lib_cfg_ringstatusget, sizeof (struct res_lib_cfg_ringstatusget)); @@ -12831,7 +16517,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c } static void message_handler_req_lib_cfg_ringreenable ( -@@ -346,7 +653,7 @@ +@@ -346,7 +665,7 @@ struct req_exec_cfg_ringreenable req_exec_cfg_ringreenable; struct iovec iovec; @@ -12840,7 +16526,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c req_exec_cfg_ringreenable.header.size = sizeof (struct req_exec_cfg_ringreenable); req_exec_cfg_ringreenable.header.id = SERVICE_ID_MAKE (CFG_SERVICE, -@@ -358,27 +665,56 @@ +@@ -358,27 +677,56 @@ assert (api->totem_mcast (&iovec, 1, TOTEM_SAFE) == 0); @@ -12902,7 +16588,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c } static void message_handler_req_lib_cfg_administrativestateset ( -@@ -386,16 +722,17 @@ +@@ -386,16 +734,17 @@ void *msg) { // struct req_lib_cfg_administrativestateset *req_lib_cfg_administrativestateset = (struct req_lib_cfg_administrativestateset *)message; @@ -12924,7 +16610,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c } static void message_handler_req_lib_cfg_serviceload ( -@@ -406,7 +743,7 @@ +@@ -406,7 +755,7 @@ (struct req_lib_cfg_serviceload *)msg; struct res_lib_cfg_serviceload res_lib_cfg_serviceload; @@ -12933,7 +16619,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c api->service_link_and_init ( api, (char *)req_lib_cfg_serviceload->service_name, -@@ -414,12 +751,12 @@ +@@ -414,12 +763,12 @@ res_lib_cfg_serviceload.header.id = MESSAGE_RES_CFG_SERVICEUNLOAD; res_lib_cfg_serviceload.header.size = sizeof (struct res_lib_cfg_serviceload); @@ -12948,7 +16634,7 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c } static void message_handler_req_lib_cfg_serviceunload ( -@@ -430,17 +767,193 @@ +@@ -430,17 +779,225 @@ (struct req_lib_cfg_serviceunload *)msg; struct res_lib_cfg_serviceunload res_lib_cfg_serviceunload; @@ -13144,10 +16830,49 @@ diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c + } + check_shutdown_status(); + LEAVE(); ++} ++ ++static void message_handler_req_lib_cfg_get_node_addrs (void *conn, void *msg) ++{ ++ struct totem_ip_address node_ifs[INTERFACE_MAX]; ++ char buf[PIPE_BUF]; ++ char **status; ++ unsigned int num_interfaces = 0; ++ int ret = 0; ++ int i; ++ struct req_lib_cfg_get_node_addrs *req_lib_cfg_get_node_addrs = (struct req_lib_cfg_get_node_addrs *)msg; ++ struct res_lib_cfg_get_node_addrs *res_lib_cfg_get_node_addrs = (struct res_lib_cfg_get_node_addrs *)buf; ++ ++ if (req_lib_cfg_get_node_addrs->nodeid == 0) ++ req_lib_cfg_get_node_addrs->nodeid = api->totem_nodeid_get(); ++ ++ api->totem_ifaces_get(req_lib_cfg_get_node_addrs->nodeid, node_ifs, &status, &num_interfaces); ++ ++ res_lib_cfg_get_node_addrs->header.size = sizeof(struct res_lib_cfg_get_node_addrs) + (num_interfaces * TOTEMIP_ADDRLEN); ++ res_lib_cfg_get_node_addrs->header.id = MESSAGE_RES_CFG_GET_NODE_ADDRS; ++ res_lib_cfg_get_node_addrs->header.error = ret; ++ res_lib_cfg_get_node_addrs->num_addrs = num_interfaces; ++ if (num_interfaces) { ++ res_lib_cfg_get_node_addrs->family = node_ifs[0].family; ++ for (i = 0; iaddrs[i][0], node_ifs[i].addr, TOTEMIP_ADDRLEN); ++ } ++ } ++ else { ++ res_lib_cfg_get_node_addrs->header.error = CS_ERR_NOT_EXIST; ++ } ++ api->ipc_conn_send_response(conn, res_lib_cfg_get_node_addrs, res_lib_cfg_get_node_addrs->header.size); } diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c --- corosync-0.92/services/confdb.c 2008-09-03 09:58:08.000000000 +0200 -+++ corosync-trunk/services/confdb.c 2008-12-08 16:55:41.000000000 +0100 ++++ corosync-trunk/services/confdb.c 2009-01-23 16:41:06.000000000 +0100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2008 Red Hat, Inc. ++ * Copyright (c) 2008-2009 Red Hat, Inc. + * + * All rights reserved. + * @@ -38,7 +38,7 @@ #include #include @@ -13325,22 +17050,22 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_OBJECT_DESTROY; -@@ -322,12 +324,12 @@ +@@ -322,12 +324,10 @@ { struct req_lib_confdb_object_find_destroy *req_lib_confdb_object_find_destroy = (struct req_lib_confdb_object_find_destroy *)message; mar_res_header_t res; - int ret = SA_AIS_OK; +- +- log_printf(LOG_LEVEL_DEBUG, "object_find_destroy for conn=%p, %d\n", conn, req_lib_confdb_object_find_destroy->find_handle); + int ret = CS_OK; - log_printf(LOG_LEVEL_DEBUG, "object_find_destroy for conn=%p, %d\n", conn, req_lib_confdb_object_find_destroy->find_handle); - if (api->object_find_destroy(req_lib_confdb_object_find_destroy->find_handle)) - ret = SA_AIS_ERR_ACCESS; + ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_OBJECT_FIND_DESTROY; -@@ -340,14 +342,14 @@ +@@ -340,14 +340,14 @@ { struct req_lib_confdb_key_create *req_lib_confdb_key_create = (struct req_lib_confdb_key_create *)message; mar_res_header_t res; @@ -13357,7 +17082,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_CREATE; -@@ -361,14 +363,14 @@ +@@ -361,14 +361,14 @@ struct res_lib_confdb_key_get res_lib_confdb_key_get; int value_len; void *value; @@ -13374,7 +17099,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c else { memcpy(res_lib_confdb_key_get.value.value, value, value_len); res_lib_confdb_key_get.value.length = value_len; -@@ -384,15 +386,13 @@ +@@ -384,15 +384,13 @@ { struct req_lib_confdb_key_get *req_lib_confdb_key_get = (struct req_lib_confdb_key_get *)message; struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec; @@ -13392,7 +17117,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec); res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_INCREMENT; -@@ -404,15 +404,13 @@ +@@ -404,15 +402,13 @@ { struct req_lib_confdb_key_get *req_lib_confdb_key_get = (struct req_lib_confdb_key_get *)message; struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec; @@ -13410,7 +17135,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec); res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_DECREMENT; -@@ -424,7 +422,7 @@ +@@ -424,7 +420,7 @@ { struct req_lib_confdb_key_replace *req_lib_confdb_key_replace = (struct req_lib_confdb_key_replace *)message; mar_res_header_t res; @@ -13419,7 +17144,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c if (api->object_key_replace(req_lib_confdb_key_replace->object_handle, req_lib_confdb_key_replace->key_name.value, -@@ -433,7 +431,7 @@ +@@ -433,7 +429,7 @@ req_lib_confdb_key_replace->old_value.length, req_lib_confdb_key_replace->new_value.value, req_lib_confdb_key_replace->new_value.length)) @@ -13428,7 +17153,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_REPLACE; -@@ -445,14 +443,14 @@ +@@ -445,14 +441,14 @@ { struct req_lib_confdb_key_delete *req_lib_confdb_key_delete = (struct req_lib_confdb_key_delete *)message; mar_res_header_t res; @@ -13445,7 +17170,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_DELETE; -@@ -465,11 +463,11 @@ +@@ -465,11 +461,11 @@ struct req_lib_confdb_object_parent_get *req_lib_confdb_object_parent_get = (struct req_lib_confdb_object_parent_get *)message; struct res_lib_confdb_object_parent_get res_lib_confdb_object_parent_get; unsigned int object_handle; @@ -13459,7 +17184,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c res_lib_confdb_object_parent_get.parent_object_handle = object_handle; res_lib_confdb_object_parent_get.header.size = sizeof(res_lib_confdb_object_parent_get); -@@ -487,7 +485,7 @@ +@@ -487,7 +483,7 @@ int key_name_len; void *value; int value_len; @@ -13468,7 +17193,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c if (api->object_key_iter_from(req_lib_confdb_key_iter->parent_object_handle, req_lib_confdb_key_iter->next_entry, -@@ -495,7 +493,7 @@ +@@ -495,7 +491,7 @@ &key_name_len, &value, &value_len)) @@ -13477,7 +17202,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c else { memcpy(res_lib_confdb_key_iter.key_name.value, key_name, key_name_len); memcpy(res_lib_confdb_key_iter.value.value, value, value_len); -@@ -514,7 +512,7 @@ +@@ -514,7 +510,7 @@ struct req_lib_confdb_object_iter *req_lib_confdb_object_iter = (struct req_lib_confdb_object_iter *)message; struct res_lib_confdb_object_iter res_lib_confdb_object_iter; int object_name_len; @@ -13486,12 +17211,16 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c if (!req_lib_confdb_object_iter->find_handle) { api->object_find_create(req_lib_confdb_object_iter->parent_object_handle, -@@ -526,7 +524,7 @@ +@@ -525,8 +521,10 @@ + res_lib_confdb_object_iter.find_handle = req_lib_confdb_object_iter->find_handle; if (api->object_find_next(res_lib_confdb_object_iter.find_handle, - &res_lib_confdb_object_iter.object_handle)) +- &res_lib_confdb_object_iter.object_handle)) - ret = SA_AIS_ERR_ACCESS; ++ &res_lib_confdb_object_iter.object_handle)) { + ret = CS_ERR_ACCESS; ++ api->object_find_destroy(res_lib_confdb_object_iter.find_handle); ++ } else { api->object_name_get(res_lib_confdb_object_iter.object_handle, (char *)res_lib_confdb_object_iter.object_name.value, @@ -13504,16 +17233,20 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c if (!req_lib_confdb_object_find->find_handle) { api->object_find_create(req_lib_confdb_object_find->parent_object_handle, -@@ -558,7 +556,7 @@ +@@ -557,8 +555,10 @@ + res_lib_confdb_object_find.find_handle = req_lib_confdb_object_find->find_handle; if (api->object_find_next(res_lib_confdb_object_find.find_handle, - &res_lib_confdb_object_find.object_handle)) +- &res_lib_confdb_object_find.object_handle)) - ret = SA_AIS_ERR_ACCESS; ++ &res_lib_confdb_object_find.object_handle)) { + ret = CS_ERR_ACCESS; ++ api->object_find_destroy(res_lib_confdb_object_find.find_handle); ++ } res_lib_confdb_object_find.header.size = sizeof(res_lib_confdb_object_find); res_lib_confdb_object_find.header.id = MESSAGE_RES_CONFDB_OBJECT_FIND; -@@ -571,11 +569,11 @@ +@@ -571,11 +571,11 @@ static void message_handler_req_lib_confdb_write (void *conn, void *message) { struct res_lib_confdb_write res_lib_confdb_write; @@ -13527,7 +17260,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c res_lib_confdb_write.header.size = sizeof(res_lib_confdb_write); res_lib_confdb_write.header.id = MESSAGE_RES_CONFDB_WRITE; -@@ -593,11 +591,11 @@ +@@ -593,11 +593,11 @@ { struct req_lib_confdb_reload *req_lib_confdb_reload = (struct req_lib_confdb_reload *)message; struct res_lib_confdb_reload res_lib_confdb_reload; @@ -13541,7 +17274,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c res_lib_confdb_reload.header.size = sizeof(res_lib_confdb_reload); res_lib_confdb_reload.header.id = MESSAGE_RES_CONFDB_RELOAD; -@@ -624,7 +622,7 @@ +@@ -624,7 +624,7 @@ res.header.size = sizeof(res); res.header.id = MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK; @@ -13550,7 +17283,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c // handle & type res.change_type = change_type; res.parent_object_handle = parent_object_handle; -@@ -651,7 +649,7 @@ +@@ -651,7 +651,7 @@ res.header.size = sizeof(res); res.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE_CALLBACK; @@ -13559,7 +17292,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c res.parent_object_handle = parent_object_handle; res.object_handle = object_handle; memcpy(res.name.value, name_pt, name_len); -@@ -668,7 +666,7 @@ +@@ -668,7 +668,7 @@ res.header.size = sizeof(res); res.header.id = MESSAGE_RES_CONFDB_OBJECT_DESTROY_CALLBACK; @@ -13568,7 +17301,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c res.parent_object_handle = parent_object_handle; memcpy(res.name.value, name_pt, name_len); res.name.length = name_len; -@@ -686,10 +684,11 @@ +@@ -686,10 +686,11 @@ confdb_notify_lib_of_key_change, confdb_notify_lib_of_new_object, confdb_notify_lib_of_destroyed_object, @@ -13581,7 +17314,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c api->ipc_conn_send_response(conn, &res, sizeof(res)); } -@@ -700,11 +699,12 @@ +@@ -700,11 +701,12 @@ api->object_track_stop(confdb_notify_lib_of_key_change, confdb_notify_lib_of_new_object, confdb_notify_lib_of_destroyed_object, @@ -13597,7 +17330,7 @@ diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c --- corosync-0.92/services/cpg.c 2008-09-17 21:15:00.000000000 +0200 -+++ corosync-trunk/services/cpg.c 2008-12-01 18:43:40.000000000 +0100 ++++ corosync-trunk/services/cpg.c 2009-01-08 07:29:16.000000000 +0100 @@ -51,7 +51,7 @@ #include #include @@ -13692,7 +17425,15 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c res = (struct res_lib_cpg_confchg_callback *)buf; res->joined_list_entries = joined_list_entries; -@@ -453,7 +453,7 @@ +@@ -404,6 +404,7 @@ + + res->header.size = size; + res->header.id = id; ++ res->header.error = CS_OK; + memcpy(&res->group_name, &gi->group_name, sizeof(mar_cpg_name_t)); + + /* Build up the message */ +@@ -453,7 +454,7 @@ } } @@ -13701,7 +17442,16 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c } static void remove_group(struct group_info *gi) -@@ -694,7 +694,7 @@ +@@ -571,6 +572,8 @@ + return; + } + } ++ if (!buf) ++ continue; + + res = (struct res_lib_cpg_groups_get_callback *)buf; + retgi = res->member_list; +@@ -694,7 +697,7 @@ struct memb_ring_id *ring_id) { int i; @@ -13710,7 +17460,7 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c struct iovec req_exec_cpg_iovec; /* We don't send the library joinlist in here because it can end up -@@ -736,7 +736,7 @@ +@@ -736,7 +739,7 @@ static void cpg_flow_control_state_set_fn ( void *context, @@ -13719,7 +17469,7 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c { struct res_lib_cpg_flowcontrol_callback res_lib_cpg_flowcontrol_callback; struct process_info *process_info = (struct process_info *)context; -@@ -1105,19 +1105,19 @@ +@@ -1105,19 +1108,19 @@ struct process_info *pi = (struct process_info *)api->ipc_private_data_get (conn); struct res_lib_cpg_join res_lib_cpg_join; struct group_info *gi; @@ -13742,7 +17492,7 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c goto join_err; } -@@ -1151,12 +1151,12 @@ +@@ -1151,12 +1154,12 @@ struct process_info *pi = (struct process_info *)api->ipc_private_data_get (conn); struct res_lib_cpg_leave res_lib_cpg_leave; struct group_info *gi; @@ -13757,7 +17507,7 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c goto leave_ret; } gi = pi->group; -@@ -1198,7 +1198,7 @@ +@@ -1198,7 +1201,7 @@ if (!gi) { res_lib_cpg_mcast.header.size = sizeof(res_lib_cpg_mcast); res_lib_cpg_mcast.header.id = MESSAGE_RES_CPG_MCAST; @@ -13766,7 +17516,7 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c res_lib_cpg_mcast.flow_control_state = CPG_FLOW_CONTROL_DISABLED; api->ipc_conn_send_response(conn, &res_lib_cpg_mcast, sizeof(res_lib_cpg_mcast)); -@@ -1225,7 +1225,7 @@ +@@ -1225,7 +1228,7 @@ res_lib_cpg_mcast.header.size = sizeof(res_lib_cpg_mcast); res_lib_cpg_mcast.header.id = MESSAGE_RES_CPG_MCAST; @@ -13775,7 +17525,7 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c res_lib_cpg_mcast.flow_control_state = pi->flow_control_state; api->ipc_conn_send_response(conn, &res_lib_cpg_mcast, sizeof(res_lib_cpg_mcast)); -@@ -1240,7 +1240,7 @@ +@@ -1240,7 +1243,7 @@ mar_res_header_t res; res.size = sizeof(res); res.id = MESSAGE_RES_CPG_MEMBERSHIP; @@ -13784,7 +17534,7 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c api->ipc_conn_send_response(conn, &res, sizeof(res)); return; } -@@ -1256,13 +1256,13 @@ +@@ -1256,13 +1259,13 @@ struct group_info *gi; struct process_info *otherpi; void *otherconn; @@ -13800,7 +17550,7 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c goto tstart_ret; } -@@ -1274,7 +1274,7 @@ +@@ -1274,7 +1277,7 @@ tstart_ret: res_lib_cpg_trackstart.header.size = sizeof(res_lib_cpg_trackstart); res_lib_cpg_trackstart.header.id = MESSAGE_RES_CPG_TRACKSTART; @@ -13809,7 +17559,7 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c api->ipc_conn_send_response(conn, &res_lib_cpg_trackstart, sizeof(res_lib_cpg_trackstart)); } -@@ -1285,13 +1285,13 @@ +@@ -1285,13 +1288,13 @@ struct process_info *otherpi; void *otherconn; struct group_info *gi; @@ -13825,7 +17575,7 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c goto tstop_ret; } -@@ -1303,7 +1303,7 @@ +@@ -1303,7 +1306,7 @@ tstop_ret: res_lib_cpg_trackstop.header.size = sizeof(res_lib_cpg_trackstop); res_lib_cpg_trackstop.header.id = MESSAGE_RES_CPG_TRACKSTOP; @@ -13834,7 +17584,7 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c api->ipc_conn_send_response(conn, &res_lib_cpg_trackstop.header, sizeof(res_lib_cpg_trackstop)); } -@@ -1313,7 +1313,7 @@ +@@ -1313,7 +1316,7 @@ res_lib_cpg_local_get.header.size = sizeof(res_lib_cpg_local_get); res_lib_cpg_local_get.header.id = MESSAGE_RES_CPG_LOCAL_GET; @@ -13843,7 +17593,7 @@ diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c res_lib_cpg_local_get.local_nodeid = api->totem_nodeid_get (); api->ipc_conn_send_response(conn, &res_lib_cpg_local_get, -@@ -1326,7 +1326,7 @@ +@@ -1326,7 +1329,7 @@ res_lib_cpg_groups_get.header.size = sizeof(res_lib_cpg_groups_get); res_lib_cpg_groups_get.header.id = MESSAGE_RES_CPG_GROUPS_GET; @@ -14018,7 +17768,7 @@ diff -Naurd corosync-0.92/services/evs.c corosync-trunk/services/evs.c msg_addr = (char *)req_exec_evs_mcast + sizeof (struct req_exec_evs_mcast) + diff -Naurd corosync-0.92/services/Makefile corosync-trunk/services/Makefile --- corosync-0.92/services/Makefile 2008-08-15 08:15:26.000000000 +0200 -+++ corosync-trunk/services/Makefile 2008-12-08 16:55:41.000000000 +0100 ++++ corosync-trunk/services/Makefile 2009-01-26 11:46:08.000000000 +0100 @@ -50,12 +50,12 @@ endif @@ -14031,27 +17781,36 @@ diff -Naurd corosync-0.92/services/Makefile corosync-trunk/services/Makefile override CFLAGS += -fPIC -all: service_evs.lcrso service_cfg.lcrso service_cpg.lcrso service_confdb.lcrso -+all: service_evs.lcrso service_cfg.lcrso service_cpg.lcrso service_confdb.lcrso service_pload.lcrso testquorum.lcrso ++all: service_evs.lcrso service_cfg.lcrso service_cpg.lcrso service_confdb.lcrso service_pload.lcrso testquorum.lcrso service_votequorum.lcrso ifeq (${COROSYNC_COMPAT}, DARWIN) -@@ -71,6 +71,9 @@ +@@ -71,6 +71,15 @@ service_cpg.lcrso: cpg.o $(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ../exec/corosync -bind_at_load cpg.o -o $@ +service_pload.lcrso: pload.o + $(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ../exec/corosync -bind_at_load pload.o -o $@ ++ ++service_votequorum.lcrso: votequorum.o ++ $(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ../exec/corosync -bind_at_load votequorum.o -o $@ ++ ++testquorum.lcrso: testquorum.o ++ $(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ../exec/corosync -bind_at_load testquorum.o -o $@ + else service_evs.lcrso: evs.o -@@ -85,11 +88,20 @@ +@@ -85,11 +94,23 @@ service_cpg.lcrso: cpg.o $(CC) -shared -Wl,-soname,service_cpg.lcrso cpg.o -o $@ +service_pload.lcrso: pload.o + $(CC) -shared -Wl,-soname,service_pload.lcrso pload.o -o $@ + ++service_votequorum.lcrso: votequorum.o ++ $(CC) -shared -Wl,-soname,service_votequorum.lcrso votequorum.o -o $@ ++ +testquorum.lcrso: testquorum.o + $(CC) -shared -Wl,-soname,testquorum.lcrso testquorum.o -o $@ + @@ -14066,7 +17825,7 @@ diff -Naurd corosync-0.92/services/Makefile corosync-trunk/services/Makefile depend: makedepend -Y -- $(CFLAGS) $(CPPFLAGS) $(EXEC_SRC) $(TOTEM_SRC) $(LOGSYS_SRC) $(LCR_SRC) > /dev/null 2>&1 -@@ -104,3 +116,6 @@ +@@ -104,3 +125,6 @@ cpg.o: cpg.c $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< @@ -14590,6 +18349,1629 @@ diff -Naurd corosync-0.92/services/testquorum.c corosync-trunk/services/testquor + /* Register for quorum changes too! */ + api->quorum_register_callback(quorum_callback, NULL); +} +diff -Naurd corosync-0.92/services/votequorum.c corosync-trunk/services/votequorum.c +--- corosync-0.92/services/votequorum.c 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/services/votequorum.c 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,1619 @@ ++/* ++ * Copyright (c) 2009 Red Hat, Inc. ++ * ++ * All rights reserved. ++ * ++ * Author: Christine Caulfield (ccaulfie@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 CONTIBUTORS "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 ++#ifndef COROSYNC_BSD ++#include ++#endif ++#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 ++ ++#define VOTEQUORUM_MAJOR_VERSION 6 ++#define VOTEQUORUM_MINOR_VERSION 3 ++#define VOTEQUORUM_PATCH_VERSION 0 ++ ++ /* Silly default to prevent accidents! */ ++#define DEFAULT_EXPECTED 1024 ++#define DEFAULT_QDEV_POLL 10000 ++ ++LOGSYS_DECLARE_SUBSYS ("VOTEQ", LOG_INFO); ++ ++enum quorum_message_req_types { ++ MESSAGE_REQ_EXEC_VOTEQUORUM_NODEINFO = 0, ++ MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE = 1, ++ MESSAGE_REQ_EXEC_VOTEQUORUM_KILLNODE = 2, ++}; ++ ++#define NODE_FLAGS_BEENDOWN 1 ++#define NODE_FLAGS_SEESDISALLOWED 8 ++#define NODE_FLAGS_HASSTATE 16 ++#define NODE_FLAGS_QDISK 32 ++#define NODE_FLAGS_REMOVED 64 ++#define NODE_FLAGS_US 128 ++ ++ ++typedef enum { NODESTATE_JOINING=1, NODESTATE_MEMBER, ++ NODESTATE_DEAD, NODESTATE_LEAVING, NODESTATE_DISALLOWED } nodestate_t; ++ ++ ++/* This structure is tacked onto the start of a cluster message packet for our ++ * own nefarious purposes. */ ++struct q_protheader { ++ unsigned char tgtport; /* Target port number */ ++ unsigned char srcport; /* Source (originating) port number */ ++ unsigned short pad; ++ unsigned int flags; ++ int srcid; /* Node ID of the sender */ ++ int tgtid; /* Node ID of the target */ ++} __attribute__((packed)); ++ ++struct cluster_node { ++ int flags; ++ int node_id; ++ unsigned int expected_votes; ++ unsigned int votes; ++ time_t join_time; ++ ++ nodestate_t state; ++ ++ struct timeval last_hello; /* Only used for quorum devices */ ++ ++ struct list_head list; ++}; ++ ++static int quorum_flags; ++#define VOTEQUORUM_FLAG_FEATURE_DISALLOWED 1 ++#define VOTEQUORUM_FLAG_FEATURE_TWONODE 1 ++ ++static int quorum; ++static int cluster_is_quorate; ++static int first_trans = 1; ++static unsigned int quorumdev_poll = DEFAULT_QDEV_POLL; ++ ++static struct cluster_node *us; ++static struct cluster_node *quorum_device = NULL; ++static char quorum_device_name[VOTEQUORUM_MAX_QDISK_NAME_LEN]; ++static corosync_timer_handle_t quorum_device_timer; ++static struct list_head cluster_members_list; ++static struct corosync_api_v1 *corosync_api; ++static struct list_head trackers_list; ++static unsigned int quorum_members[PROCESSOR_COUNT_MAX+1]; ++static int quorum_members_entries = 0; ++static struct memb_ring_id quorum_ringid; ++static cs_tpg_handle group_handle; ++ ++#define max(a,b) (((a) > (b)) ? (a) : (b)) ++static struct cluster_node *find_node_by_nodeid(int nodeid); ++static struct cluster_node *allocate_node(int nodeid); ++static char *kill_reason(int reason); ++ ++static struct corosync_tpg_group quorum_group[1] = { ++ { .group = "VOTEQ", .group_len = 5}, ++}; ++ ++#define list_iterate(v, head) \ ++ for (v = (head)->next; v != head; v = v->next) ++ ++struct quorum_pd { ++ unsigned char track_flags; ++ int tracking_enabled; ++ uint64_t tracking_context; ++ struct list_head list; ++ void *conn; ++}; ++ ++/* ++ * Service Interfaces required by service_message_handler struct ++ */ ++ ++static void votequorum_init(struct corosync_api_v1 *api, ++ quorum_set_quorate_fn_t report); ++ ++static void quorum_confchg_fn ( ++ enum totem_configuration_type configuration_type, ++ unsigned int *member_list, int member_list_entries, ++ unsigned int *left_list, int left_list_entries, ++ unsigned int *joined_list, int joined_list_entries, ++ struct memb_ring_id *ring_id); ++ ++static void quorum_deliver_fn(unsigned int nodeid, struct iovec *iovec, int iov_len, ++ int endian_conversion_required); ++ ++static int votequorum_exec_init_fn (struct corosync_api_v1 *corosync_api); ++ ++static int quorum_lib_init_fn (void *conn); ++ ++static int quorum_lib_exit_fn (void *conn); ++ ++static void message_handler_req_exec_quorum_nodeinfo ( ++ void *message, ++ unsigned int nodeid); ++ ++static void message_handler_req_exec_quorum_reconfigure ( ++ void *message, ++ unsigned int nodeid); ++ ++static void message_handler_req_exec_quorum_killnode ( ++ void *message, ++ unsigned int nodeid); ++ ++ ++static void message_handler_req_lib_votequorum_getinfo (void *conn, void *message); ++ ++static void message_handler_req_lib_votequorum_setexpected (void *conn, void *message); ++ ++static void message_handler_req_lib_votequorum_setvotes (void *conn, void *message); ++ ++static void message_handler_req_lib_votequorum_qdisk_register (void *conn, void *message); ++ ++static void message_handler_req_lib_votequorum_qdisk_unregister (void *conn, void *message); ++ ++static void message_handler_req_lib_votequorum_qdisk_poll (void *conn, void *message); ++ ++static void message_handler_req_lib_votequorum_qdisk_getinfo (void *conn, void *message); ++ ++static void message_handler_req_lib_votequorum_setstate (void *conn, void *message); ++ ++static void message_handler_req_lib_votequorum_leaving (void *conn, void *message); ++static void message_handler_req_lib_votequorum_trackstart (void *conn, void *msg); ++static void message_handler_req_lib_votequorum_trackstop (void *conn, void *msg); ++ ++static int quorum_exec_send_nodeinfo(void); ++static int quorum_exec_send_reconfigure(int param, int nodeid, int value); ++static int quorum_exec_send_killnode(int nodeid, unsigned int reason); ++ ++static void add_votequorum_config_notification(unsigned int quorum_object_handle); ++ ++ ++/* ++ * Library Handler Definition ++ */ ++static struct corosync_lib_handler quorum_lib_service[] = ++{ ++ { /* 0 */ ++ .lib_handler_fn = message_handler_req_lib_votequorum_getinfo, ++ .response_size = sizeof (struct res_lib_votequorum_getinfo), ++ .response_id = MESSAGE_RES_VOTEQUORUM_GETINFO, ++ .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED ++ }, ++ { /* 1 */ ++ .lib_handler_fn = message_handler_req_lib_votequorum_setexpected, ++ .response_size = sizeof (struct res_lib_votequorum_status), ++ .response_id = MESSAGE_RES_VOTEQUORUM_STATUS, ++ .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED ++ }, ++ { /* 2 */ ++ .lib_handler_fn = message_handler_req_lib_votequorum_setvotes, ++ .response_size = sizeof (struct res_lib_votequorum_status), ++ .response_id = MESSAGE_RES_VOTEQUORUM_STATUS, ++ .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED ++ }, ++ { /* 3 */ ++ .lib_handler_fn = message_handler_req_lib_votequorum_qdisk_register, ++ .response_size = sizeof (struct res_lib_votequorum_status), ++ .response_id = MESSAGE_RES_VOTEQUORUM_STATUS, ++ .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED ++ }, ++ { /* 4 */ ++ .lib_handler_fn = message_handler_req_lib_votequorum_qdisk_unregister, ++ .response_size = sizeof (struct res_lib_votequorum_status), ++ .response_id = MESSAGE_RES_VOTEQUORUM_STATUS, ++ .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED ++ }, ++ { /* 5 */ ++ .lib_handler_fn = message_handler_req_lib_votequorum_qdisk_poll, ++ .response_size = sizeof (struct res_lib_votequorum_status), ++ .response_id = MESSAGE_RES_VOTEQUORUM_STATUS, ++ .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED ++ }, ++ { /* 6 */ ++ .lib_handler_fn = message_handler_req_lib_votequorum_qdisk_getinfo, ++ .response_size = sizeof (struct res_lib_votequorum_qdisk_getinfo), ++ .response_id = MESSAGE_RES_VOTEQUORUM_QDISK_GETINFO, ++ .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED ++ }, ++ { /* 7 */ ++ .lib_handler_fn = message_handler_req_lib_votequorum_setstate, ++ .response_size = sizeof (struct res_lib_votequorum_status), ++ .response_id = MESSAGE_RES_VOTEQUORUM_STATUS, ++ .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED ++ }, ++ { /* 8 */ ++ .lib_handler_fn = message_handler_req_lib_votequorum_leaving, ++ .response_size = sizeof (struct res_lib_votequorum_status), ++ .response_id = MESSAGE_RES_VOTEQUORUM_STATUS, ++ .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED ++ }, ++ { /* 9 */ ++ .lib_handler_fn = message_handler_req_lib_votequorum_trackstart, ++ .response_size = sizeof (struct res_lib_votequorum_status), ++ .response_id = MESSAGE_RES_VOTEQUORUM_STATUS, ++ .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED ++ }, ++ { /* 10 */ ++ .lib_handler_fn = message_handler_req_lib_votequorum_trackstop, ++ .response_size = sizeof (struct res_lib_votequorum_status), ++ .response_id = MESSAGE_RES_VOTEQUORUM_STATUS, ++ .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED ++ } ++}; ++ ++static quorum_set_quorate_fn_t set_quorum; ++/* ++ * lcrso object definition ++ */ ++static struct quorum_services_api_ver1 votequorum_iface_ver0 = { ++ .init = votequorum_init ++}; ++ ++static struct corosync_service_engine quorum_service_handler = { ++ .name = "corosync votes quorum service v0.90", ++ .id = VOTEQUORUM_SERVICE, ++ .private_data_size = sizeof (struct quorum_pd), ++ .allow_inquorate = CS_LIB_ALLOW_INQUORATE, ++ .flow_control = COROSYNC_LIB_FLOW_CONTROL_REQUIRED, ++ .lib_init_fn = quorum_lib_init_fn, ++ .lib_exit_fn = quorum_lib_exit_fn, ++ .lib_engine = quorum_lib_service, ++ .lib_engine_count = sizeof (quorum_lib_service) / sizeof (struct corosync_lib_handler), ++ .exec_init_fn = votequorum_exec_init_fn, ++ .exec_engine = NULL, ++ .exec_engine_count = 0, ++ .confchg_fn = NULL, ++}; ++ ++/* ++ * Dynamic loader definition ++ */ ++static struct corosync_service_engine *quorum_get_service_handler_ver0 (void); ++ ++static struct corosync_service_engine_iface_ver0 quorum_service_handler_iface = { ++ .corosync_get_service_engine_ver0 = quorum_get_service_handler_ver0 ++}; ++ ++static struct lcr_iface corosync_quorum_ver0[2] = { ++ { ++ .name = "corosync_votequorum", ++ .version = 0, ++ .versions_replace = 0, ++ .versions_replace_count = 0, ++ .dependencies = 0, ++ .dependency_count = 0, ++ .constructor = NULL, ++ .destructor = NULL, ++ .interfaces = (void **)(void *)&votequorum_iface_ver0 ++ }, ++ { ++ .name = "corosync_votequorum_iface", ++ .version = 0, ++ .versions_replace = 0, ++ .versions_replace_count = 0, ++ .dependencies = 0, ++ .dependency_count = 0, ++ .constructor = NULL, ++ .destructor = NULL, ++ .interfaces = NULL ++ } ++}; ++ ++static struct lcr_comp quorum_comp_ver0 = { ++ .iface_count = 2, ++ .ifaces = corosync_quorum_ver0 ++}; ++ ++ ++static struct corosync_service_engine *quorum_get_service_handler_ver0 (void) ++{ ++ return (&quorum_service_handler); ++} ++ ++__attribute__ ((constructor)) static void quorum_comp_register (void) { ++ lcr_interfaces_set (&corosync_quorum_ver0[0], &votequorum_iface_ver0); ++ lcr_interfaces_set (&corosync_quorum_ver0[1], &quorum_service_handler_iface); ++ lcr_component_register (&quorum_comp_ver0); ++} ++ ++static void votequorum_init(struct corosync_api_v1 *api, ++ quorum_set_quorate_fn_t report) ++{ ++ ENTER(); ++ set_quorum = report; ++ ++ /* Load the library-servicing part of this module */ ++ api->service_link_and_init(api, "corosync_votequorum_iface", 0); ++ ++ LEAVE(); ++} ++ ++/* Message types */ ++#define VOTEQUORUM_MSG_NODEINFO 5 ++#define VOTEQUORUM_MSG_KILLNODE 6 ++#define VOTEQUORUM_MSG_RECONFIGURE 8 ++ ++struct req_exec_quorum_nodeinfo { ++ unsigned char cmd; ++ unsigned char first_trans; ++ unsigned int votes; ++ unsigned int expected_votes; ++ ++ unsigned int major_version; /* Not backwards compatible */ ++ unsigned int minor_version; /* Backwards compatible */ ++ unsigned int patch_version; /* Backwards/forwards compatible */ ++ unsigned int config_version; ++ unsigned int flags; ++ ++} __attribute__((packed)); ++ ++/* Parameters for RECONFIG command */ ++#define RECONFIG_PARAM_EXPECTED_VOTES 1 ++#define RECONFIG_PARAM_NODE_VOTES 2 ++#define RECONFIG_PARAM_LEAVING 3 ++ ++struct req_exec_quorum_reconfigure { ++ unsigned char cmd; ++ unsigned char param; ++ unsigned short pad; ++ int nodeid; ++ unsigned int value; ++}; ++ ++struct req_exec_quorum_killnode { ++ unsigned char cmd; ++ unsigned char pad1; ++ uint16_t reason; ++ int nodeid; ++}; ++ ++/* These just make the access a little neater */ ++static inline int objdb_get_string(struct corosync_api_v1 *corosync, unsigned int object_service_handle, ++ char *key, char **value) ++{ ++ int res; ++ ++ *value = NULL; ++ if ( !(res = corosync_api->object_key_get(object_service_handle, ++ key, ++ strlen(key), ++ (void *)value, ++ NULL))) { ++ if (*value) ++ return 0; ++ } ++ return -1; ++} ++ ++static inline void objdb_get_int(struct corosync_api_v1 *corosync, unsigned int object_service_handle, ++ char *key, unsigned int *intvalue, unsigned int default_value) ++{ ++ char *value = NULL; ++ ++ *intvalue = default_value; ++ ++ if (!corosync_api->object_key_get(object_service_handle, key, strlen(key), ++ (void *)&value, NULL)) { ++ if (value) { ++ *intvalue = atoi(value); ++ } ++ } ++} ++ ++static int votequorum_send_message(void *message, int len) ++{ ++ struct iovec iov[2]; ++ struct q_protheader header; ++ ++ header.tgtport = 0; ++ header.srcport = 0; ++ header.flags = 0; ++ header.srcid = us->node_id; ++ header.tgtid = 0; ++ ++ iov[0].iov_base = &header; ++ iov[0].iov_len = sizeof(header); ++ iov[1].iov_base = message; ++ iov[1].iov_len = len; ++ ++ return corosync_api->tpg_joined_mcast(group_handle, iov, 2, TOTEM_AGREED); ++} ++ ++static void read_quorum_config(unsigned int quorum_handle) ++{ ++ unsigned int value = 0; ++ int cluster_members = 0; ++ struct list_head *tmp; ++ struct cluster_node *node; ++ ++ log_printf(LOG_INFO, "Reading configuration\n"); ++ ++ objdb_get_int(corosync_api, quorum_handle, "expected_votes", &us->expected_votes, DEFAULT_EXPECTED); ++ objdb_get_int(corosync_api, quorum_handle, "votes", &us->votes, 1); ++ objdb_get_int(corosync_api, quorum_handle, "quorumdev_poll", &quorumdev_poll, DEFAULT_QDEV_POLL); ++ objdb_get_int(corosync_api, quorum_handle, "disallowed", &value, 0); ++ if (value) ++ quorum_flags |= VOTEQUORUM_FLAG_FEATURE_DISALLOWED; ++ else ++ quorum_flags &= ~VOTEQUORUM_FLAG_FEATURE_DISALLOWED; ++ ++ objdb_get_int(corosync_api, quorum_handle, "two_node", &value, 0); ++ if (value) ++ quorum_flags |= VOTEQUORUM_FLAG_FEATURE_TWONODE; ++ else ++ quorum_flags &= ~VOTEQUORUM_FLAG_FEATURE_TWONODE; ++ ++ /* ++ * two_node mode is invalid if there are more than 2 nodes in the cluster! ++ */ ++ list_iterate(tmp, &cluster_members_list) { ++ node = list_entry(tmp, struct cluster_node, list); ++ cluster_members++; ++ } ++ ++ if (quorum_flags & VOTEQUORUM_FLAG_FEATURE_TWONODE && cluster_members > 2) { ++ log_printf(LOG_WARNING, "quorum.two_node was set but there are more than 2 nodes in the cluster. It will be ignored."); ++ quorum_flags &= ~VOTEQUORUM_FLAG_FEATURE_TWONODE; ++ } ++} ++ ++static int votequorum_exec_init_fn (struct corosync_api_v1 *api) ++{ ++ unsigned int object_handle; ++ unsigned int find_handle; ++ ++ ENTER(); ++ ++ corosync_api = api; ++ ++ list_init(&cluster_members_list); ++ list_init(&trackers_list); ++ ++ /* Allocate a cluster_node for us */ ++ us = allocate_node(corosync_api->totem_nodeid_get()); ++ if (!us) ++ return (1); ++ ++ us->flags |= NODE_FLAGS_US; ++ us->state = NODESTATE_MEMBER; ++ us->expected_votes = DEFAULT_EXPECTED; ++ us->votes = 1; ++ time(&us->join_time); ++ ++ /* Get configuration variables */ ++ corosync_api->object_find_create(OBJECT_PARENT_HANDLE, "quorum", strlen("quorum"), &find_handle); ++ ++ if (corosync_api->object_find_next(find_handle, &object_handle) == 0) { ++ read_quorum_config(object_handle); ++ } ++ /* Listen for changes */ ++ add_votequorum_config_notification(object_handle); ++ corosync_api->object_find_destroy(find_handle); ++ ++ api->tpg_init(&group_handle, quorum_deliver_fn, quorum_confchg_fn); ++ api->tpg_join(group_handle, quorum_group, 1); ++ ++ LEAVE(); ++ return (0); ++} ++ ++static int quorum_lib_exit_fn (void *conn) ++{ ++ struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn); ++ ++ ENTER(); ++ if (quorum_pd->tracking_enabled) { ++ list_del (&quorum_pd->list); ++ list_init (&quorum_pd->list); ++ } ++ LEAVE(); ++ return (0); ++} ++ ++ ++static int send_quorum_notification(void *conn, uint64_t context) ++{ ++ struct res_lib_votequorum_notification *res_lib_votequorum_notification; ++ struct list_head *tmp; ++ struct cluster_node *node; ++ int cluster_members = 0; ++ int i = 0; ++ int size; ++ char *buf; ++ ++ ENTER(); ++ list_iterate(tmp, &cluster_members_list) { ++ node = list_entry(tmp, struct cluster_node, list); ++ cluster_members++; ++ } ++ if (quorum_device) ++ cluster_members++; ++ ++ size = sizeof(struct res_lib_votequorum_notification) + sizeof(struct votequorum_node) * cluster_members; ++ buf = alloca(size); ++ if (!buf) { ++ LEAVE(); ++ return -1; ++ } ++ ++ res_lib_votequorum_notification = (struct res_lib_votequorum_notification *)buf; ++ res_lib_votequorum_notification->quorate = cluster_is_quorate; ++ res_lib_votequorum_notification->node_list_entries = cluster_members; ++ res_lib_votequorum_notification->context = context; ++ list_iterate(tmp, &cluster_members_list) { ++ node = list_entry(tmp, struct cluster_node, list); ++ res_lib_votequorum_notification->node_list[i].nodeid = node->node_id; ++ res_lib_votequorum_notification->node_list[i++].state = node->state; ++ } ++ if (quorum_device) { ++ res_lib_votequorum_notification->node_list[i].nodeid = 0; ++ res_lib_votequorum_notification->node_list[i++].state = quorum_device->state | 0x80; ++ } ++ res_lib_votequorum_notification->header.id = MESSAGE_RES_VOTEQUORUM_NOTIFICATION; ++ res_lib_votequorum_notification->header.size = size; ++ res_lib_votequorum_notification->header.error = CS_OK; ++ ++ /* Send it to all interested parties */ ++ if (conn) { ++ int ret = corosync_api->ipc_conn_send_response(conn, buf, size); ++ LEAVE(); ++ return ret; ++ } ++ else { ++ struct quorum_pd *qpd; ++ ++ list_iterate(tmp, &trackers_list) { ++ qpd = list_entry(tmp, struct quorum_pd, list); ++ res_lib_votequorum_notification->context = qpd->tracking_context; ++ corosync_api->ipc_conn_send_response(corosync_api->ipc_conn_partner_get(qpd->conn), buf, size); ++ } ++ } ++ LEAVE(); ++ return 0; ++} ++ ++static void set_quorate(int total_votes) ++{ ++ int quorate; ++ ++ ENTER(); ++ if (quorum > total_votes) { ++ quorate = 0; ++ } ++ else { ++ quorate = 1; ++ } ++ ++ if (cluster_is_quorate && !quorate) ++ log_printf(LOG_INFO, "quorum lost, blocking activity\n"); ++ if (!cluster_is_quorate && quorate) ++ log_printf(LOG_INFO, "quorum regained, resuming activity\n"); ++ ++ /* If we are newly quorate, then kill any DISALLOWED nodes */ ++ if (!cluster_is_quorate && quorate) { ++ struct cluster_node *node = NULL; ++ struct list_head *tmp; ++ ++ list_iterate(tmp, &cluster_members_list) { ++ node = list_entry(tmp, struct cluster_node, list); ++ if (node->state == NODESTATE_DISALLOWED) ++ quorum_exec_send_killnode(node->node_id, VOTEQUORUM_REASON_KILL_REJOIN); ++ } ++ } ++ ++ cluster_is_quorate = quorate; ++ set_quorum(quorum_members, quorum_members_entries, quorate, &quorum_ringid); ++ ENTER(); ++} ++ ++static int calculate_quorum(int allow_decrease, int max_expected, unsigned int *ret_total_votes) ++{ ++ struct list_head *nodelist; ++ struct cluster_node *node; ++ unsigned int total_votes = 0; ++ unsigned int highest_expected = 0; ++ unsigned int newquorum, q1, q2; ++ unsigned int total_nodes = 0; ++ unsigned int leaving = 0; ++ ++ ENTER(); ++ list_iterate(nodelist, &cluster_members_list) { ++ node = list_entry(nodelist, struct cluster_node, list); ++ ++ log_printf(LOG_DEBUG, "node %x state=%d, votes=%d, expected=%d\n", ++ node->node_id, node->state, node->votes, node->expected_votes); ++ ++ if (node->state == NODESTATE_MEMBER) { ++ if (max_expected) ++ node->expected_votes = max_expected; ++ else ++ highest_expected = max(highest_expected, node->expected_votes); ++ total_votes += node->votes; ++ total_nodes++; ++ } ++ if (node->state == NODESTATE_LEAVING) { ++ leaving = 1; ++ } ++ } ++ ++ if (quorum_device && quorum_device->state == NODESTATE_MEMBER) ++ total_votes += quorum_device->votes; ++ ++ if (max_expected > 0) ++ highest_expected = max_expected; ++ ++ /* This quorum calculation is taken from the OpenVMS Cluster Systems ++ * manual, but, then, you guessed that didn't you */ ++ q1 = (highest_expected + 2) / 2; ++ q2 = (total_votes + 2) / 2; ++ newquorum = max(q1, q2); ++ ++ /* Normally quorum never decreases but the system administrator can ++ * force it down by setting expected votes to a maximum value */ ++ if (!allow_decrease) ++ newquorum = max(quorum, newquorum); ++ ++ /* The special two_node mode allows each of the two nodes to retain ++ * quorum if the other fails. Only one of the two should live past ++ * fencing (as both nodes try to fence each other in split-brain.) ++ * Also: if there are more than two nodes, force us inquorate to avoid ++ * any damage or confusion. ++ */ ++ if ((quorum_flags & VOTEQUORUM_FLAG_FEATURE_TWONODE) && total_nodes <= 2) ++ newquorum = 1; ++ ++ if (ret_total_votes) ++ *ret_total_votes = total_votes; ++ ++ LEAVE(); ++ return newquorum; ++} ++ ++/* Recalculate cluster quorum, set quorate and notify changes */ ++static void recalculate_quorum(int allow_decrease) ++{ ++ unsigned int total_votes; ++ ++ ENTER(); ++ quorum = calculate_quorum(allow_decrease, 0, &total_votes); ++ set_quorate(total_votes); ++ send_quorum_notification(NULL, 0L); ++ LEAVE(); ++} ++ ++static int have_disallowed(void) ++{ ++ struct cluster_node *node; ++ struct list_head *tmp; ++ ++ list_iterate(tmp, &cluster_members_list) { ++ node = list_entry(tmp, struct cluster_node, list); ++ if (node->state == NODESTATE_DISALLOWED) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void node_add_ordered(struct cluster_node *newnode) ++{ ++ struct cluster_node *node = NULL; ++ struct list_head *tmp; ++ struct list_head *newlist = &newnode->list; ++ ++ list_iterate(tmp, &cluster_members_list) { ++ node = list_entry(tmp, struct cluster_node, list); ++ ++ if (newnode->node_id < node->node_id) ++ break; ++ } ++ ++ if (!node) ++ list_add(&newnode->list, &cluster_members_list); ++ else { ++ newlist->prev = tmp->prev; ++ newlist->next = tmp; ++ tmp->prev->next = newlist; ++ tmp->prev = newlist; ++ } ++} ++ ++static struct cluster_node *allocate_node(int nodeid) ++{ ++ struct cluster_node *cl; ++ ++ cl = malloc(sizeof(struct cluster_node)); ++ if (cl) { ++ memset(cl, 0, sizeof(struct cluster_node)); ++ cl->node_id = nodeid; ++ if (nodeid) ++ node_add_ordered(cl); ++ } ++ return cl; ++} ++ ++static struct cluster_node *find_node_by_nodeid(int nodeid) ++{ ++ struct cluster_node *node; ++ struct list_head *tmp; ++ ++ list_iterate(tmp, &cluster_members_list) { ++ node = list_entry(tmp, struct cluster_node, list); ++ if (node->node_id == nodeid) ++ return node; ++ } ++ return NULL; ++} ++ ++ ++static int quorum_exec_send_nodeinfo() ++{ ++ struct req_exec_quorum_nodeinfo req_exec_quorum_nodeinfo; ++ int ret; ++ ++ ENTER(); ++ ++ req_exec_quorum_nodeinfo.cmd = VOTEQUORUM_MSG_NODEINFO; ++ req_exec_quorum_nodeinfo.expected_votes = us->expected_votes; ++ req_exec_quorum_nodeinfo.votes = us->votes; ++ req_exec_quorum_nodeinfo.major_version = VOTEQUORUM_MAJOR_VERSION; ++ req_exec_quorum_nodeinfo.minor_version = VOTEQUORUM_MINOR_VERSION; ++ req_exec_quorum_nodeinfo.patch_version = VOTEQUORUM_PATCH_VERSION; ++ req_exec_quorum_nodeinfo.flags = us->flags; ++ req_exec_quorum_nodeinfo.first_trans = first_trans; ++ if (have_disallowed()) ++ req_exec_quorum_nodeinfo.flags |= NODE_FLAGS_SEESDISALLOWED; ++ ++ ret = votequorum_send_message(&req_exec_quorum_nodeinfo, sizeof(req_exec_quorum_nodeinfo)); ++ LEAVE(); ++ return ret; ++} ++ ++ ++static int quorum_exec_send_reconfigure(int param, int nodeid, int value) ++{ ++ struct req_exec_quorum_reconfigure req_exec_quorum_reconfigure; ++ int ret; ++ ++ ENTER(); ++ ++ req_exec_quorum_reconfigure.cmd = VOTEQUORUM_MSG_RECONFIGURE; ++ req_exec_quorum_reconfigure.param = param; ++ req_exec_quorum_reconfigure.nodeid = nodeid; ++ req_exec_quorum_reconfigure.value = value; ++ ++ ret = votequorum_send_message(&req_exec_quorum_reconfigure, sizeof(req_exec_quorum_reconfigure)); ++ LEAVE(); ++ return ret; ++} ++ ++static int quorum_exec_send_killnode(int nodeid, unsigned int reason) ++{ ++ struct req_exec_quorum_killnode req_exec_quorum_killnode; ++ int ret; ++ ++ ENTER(); ++ ++ req_exec_quorum_killnode.cmd = VOTEQUORUM_MSG_KILLNODE; ++ req_exec_quorum_killnode.nodeid = nodeid; ++ req_exec_quorum_killnode.reason = reason; ++ ++ ret = votequorum_send_message(&req_exec_quorum_killnode, sizeof(req_exec_quorum_killnode)); ++ LEAVE(); ++ return ret; ++} ++ ++static void quorum_confchg_fn ( ++ enum totem_configuration_type configuration_type, ++ unsigned int *member_list, int member_list_entries, ++ unsigned int *left_list, int left_list_entries, ++ unsigned int *joined_list, int joined_list_entries, ++ struct memb_ring_id *ring_id) ++{ ++ int i; ++ int leaving = 0; ++ struct cluster_node *node; ++ ++ ENTER(); ++ if (member_list_entries > 1) ++ first_trans = 0; ++ ++ if (left_list_entries) { ++ for (i = 0; i< left_list_entries; i++) { ++ node = find_node_by_nodeid(left_list[i]); ++ if (node) { ++ if (node->state == NODESTATE_LEAVING) ++ leaving = 1; ++ node->state = NODESTATE_DEAD; ++ node->flags |= NODE_FLAGS_BEENDOWN; ++ } ++ } ++ recalculate_quorum(leaving); ++ } ++ ++ if (member_list_entries) { ++ memcpy(quorum_members, member_list, sizeof(unsigned int) * member_list_entries); ++ quorum_members_entries = member_list_entries; ++ if (quorum_device) { ++ quorum_members[quorum_members_entries++] = 0; ++ } ++ quorum_exec_send_nodeinfo(); ++ } ++ ++ memcpy(&quorum_ringid, ring_id, sizeof(*ring_id)); ++ LEAVE(); ++} ++ ++static void exec_quorum_nodeinfo_endian_convert (void *msg) ++{ ++ struct req_exec_quorum_nodeinfo *nodeinfo = (struct req_exec_quorum_nodeinfo *)msg; ++ ++ nodeinfo->votes = swab32(nodeinfo->votes); ++ nodeinfo->expected_votes = swab32(nodeinfo->expected_votes); ++ nodeinfo->major_version = swab32(nodeinfo->major_version); ++ nodeinfo->minor_version = swab32(nodeinfo->minor_version); ++ nodeinfo->patch_version = swab32(nodeinfo->patch_version); ++ nodeinfo->config_version = swab32(nodeinfo->config_version); ++ nodeinfo->flags = swab32(nodeinfo->flags); ++} ++ ++static void exec_quorum_reconfigure_endian_convert (void *msg) ++{ ++ struct req_exec_quorum_reconfigure *reconfigure = (struct req_exec_quorum_reconfigure *)msg; ++ reconfigure->nodeid = swab32(reconfigure->nodeid); ++ reconfigure->value = swab32(reconfigure->value); ++} ++ ++static void exec_quorum_killnode_endian_convert (void *msg) ++{ ++ struct req_exec_quorum_killnode *killnode = (struct req_exec_quorum_killnode *)msg; ++ killnode->reason = swab16(killnode->reason); ++ killnode->nodeid = swab32(killnode->nodeid); ++} ++ ++static void quorum_deliver_fn(unsigned int nodeid, struct iovec *iovec, int iov_len, ++ int endian_conversion_required) ++{ ++ struct q_protheader *header = iovec->iov_base; ++ char *buf; ++ ++ ENTER(); ++ ++ if (endian_conversion_required) { ++ header->srcid = swab32(header->srcid); ++ header->tgtid = swab32(header->tgtid); ++ header->flags = swab32(header->flags); ++ } ++ ++ /* Only pass on messages for us or everyone */ ++ if (header->tgtport == 0 && ++ (header->tgtid == us->node_id || ++ header->tgtid == 0)) { ++ buf = iovec->iov_base + sizeof(struct q_protheader); ++ switch (*buf) { ++ ++ case VOTEQUORUM_MSG_NODEINFO: ++ if (endian_conversion_required) ++ exec_quorum_nodeinfo_endian_convert(buf); ++ message_handler_req_exec_quorum_nodeinfo (buf, header->srcid); ++ break; ++ case VOTEQUORUM_MSG_RECONFIGURE: ++ if (endian_conversion_required) ++ exec_quorum_reconfigure_endian_convert(buf); ++ message_handler_req_exec_quorum_reconfigure (buf, header->srcid); ++ break; ++ case VOTEQUORUM_MSG_KILLNODE: ++ if (endian_conversion_required) ++ exec_quorum_killnode_endian_convert(buf); ++ message_handler_req_exec_quorum_killnode (buf, header->srcid); ++ break; ++ ++ /* Just ignore other messages */ ++ } ++ } ++ LEAVE(); ++} ++ ++static void message_handler_req_exec_quorum_nodeinfo ( ++ void *message, ++ unsigned int nodeid) ++{ ++ struct req_exec_quorum_nodeinfo *req_exec_quorum_nodeinfo = (struct req_exec_quorum_nodeinfo *)message; ++ struct cluster_node *node; ++ int old_votes; ++ int old_expected; ++ nodestate_t old_state; ++ int new_node = 0; ++ ++ ENTER(); ++ log_printf(LOG_LEVEL_DEBUG, "got nodeinfo message from cluster node %d\n", nodeid); ++ ++ node = find_node_by_nodeid(nodeid); ++ if (!node) { ++ node = allocate_node(nodeid); ++ new_node = 1; ++ } ++ if (!node) { ++ corosync_api->error_memory_failure(); ++ return; ++ } ++ ++ /* ++ * If the node sending the message sees disallowed nodes and we don't, then ++ * we have to leave ++ */ ++ if (req_exec_quorum_nodeinfo->flags & NODE_FLAGS_SEESDISALLOWED && !have_disallowed()) { ++ /* Must use syslog directly here or the message will never arrive */ ++ syslog(LOG_CRIT, "[VOTEQ]: Joined a cluster with disallowed nodes. must die"); ++ corosync_api->fatal_error(2, __FILE__, __LINE__); ++ exit(2); ++ } ++ old_votes = node->votes; ++ old_expected = node->expected_votes; ++ old_state = node->state; ++ ++ /* Update node state */ ++ if (req_exec_quorum_nodeinfo->minor_version >= 2) ++ node->votes = req_exec_quorum_nodeinfo->votes; ++ node->expected_votes = req_exec_quorum_nodeinfo->expected_votes; ++ node->state = NODESTATE_MEMBER; ++ ++ /* Check flags for disallowed (if enabled) */ ++ if (quorum_flags & VOTEQUORUM_FLAG_FEATURE_DISALLOWED) { ++ if ((req_exec_quorum_nodeinfo->flags & NODE_FLAGS_HASSTATE && node->flags & NODE_FLAGS_BEENDOWN) || ++ (req_exec_quorum_nodeinfo->flags & NODE_FLAGS_HASSTATE && req_exec_quorum_nodeinfo->first_trans && !(node->flags & NODE_FLAGS_US))) { ++ if (node->state != NODESTATE_DISALLOWED) { ++ if (cluster_is_quorate) { ++ log_printf(LOG_CRIT, "Killing node %d because it has rejoined the cluster with existing state", node->node_id); ++ node->state = NODESTATE_DISALLOWED; ++ quorum_exec_send_killnode(nodeid, VOTEQUORUM_REASON_KILL_REJOIN); ++ } ++ else { ++ log_printf(LOG_CRIT, "Node %d not joined to quorum because it has existing state", node->node_id); ++ node->state = NODESTATE_DISALLOWED; ++ } ++ } ++ } ++ } ++ node->flags &= ~NODE_FLAGS_BEENDOWN; ++ ++ if (new_node || old_votes != node->votes || old_expected != node->expected_votes || old_state != node->state) ++ recalculate_quorum(0); ++ LEAVE(); ++} ++ ++static void message_handler_req_exec_quorum_killnode ( ++ void *message, ++ unsigned int nodeid) ++{ ++ struct req_exec_quorum_killnode *req_exec_quorum_killnode = (struct req_exec_quorum_killnode *)message; ++ ++ if (req_exec_quorum_killnode->nodeid == corosync_api->totem_nodeid_get()) { ++ log_printf(LOG_CRIT, "Killed by node %d: %s\n", nodeid, kill_reason(req_exec_quorum_killnode->reason)); ++ ++ corosync_api->fatal_error(1, __FILE__, __LINE__); ++ exit(1); ++ } ++} ++ ++static void message_handler_req_exec_quorum_reconfigure ( ++ void *message, ++ unsigned int nodeid) ++{ ++ struct req_exec_quorum_reconfigure *req_exec_quorum_reconfigure = (struct req_exec_quorum_reconfigure *)message; ++ struct cluster_node *node; ++ struct list_head *nodelist; ++ ++ log_printf(LOG_LEVEL_DEBUG, "got reconfigure message from cluster node %d\n", nodeid); ++ ++ node = find_node_by_nodeid(req_exec_quorum_reconfigure->nodeid); ++ if (!node) ++ return; ++ ++ switch(req_exec_quorum_reconfigure->param) ++ { ++ case RECONFIG_PARAM_EXPECTED_VOTES: ++ node->expected_votes = req_exec_quorum_reconfigure->value; ++ ++ list_iterate(nodelist, &cluster_members_list) { ++ node = list_entry(nodelist, struct cluster_node, list); ++ if (node->state == NODESTATE_MEMBER && ++ node->expected_votes > req_exec_quorum_reconfigure->value) { ++ node->expected_votes = req_exec_quorum_reconfigure->value; ++ } ++ } ++ recalculate_quorum(1); /* Allow decrease */ ++ break; ++ ++ case RECONFIG_PARAM_NODE_VOTES: ++ node->votes = req_exec_quorum_reconfigure->value; ++ recalculate_quorum(1); /* Allow decrease */ ++ break; ++ ++ case RECONFIG_PARAM_LEAVING: ++ node->state = NODESTATE_LEAVING; ++ break; ++ } ++} ++ ++static int quorum_lib_init_fn (void *conn) ++{ ++ struct quorum_pd *pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn); ++ ++ ENTER(); ++ ++ list_init (&pd->list); ++ pd->conn = conn; ++ ++ LEAVE(); ++ return (0); ++} ++ ++/* Message from the library */ ++static void message_handler_req_lib_votequorum_getinfo (void *conn, void *message) ++{ ++ struct req_lib_votequorum_getinfo *req_lib_votequorum_getinfo = (struct req_lib_votequorum_getinfo *)message; ++ struct res_lib_votequorum_getinfo res_lib_votequorum_getinfo; ++ struct cluster_node *node; ++ unsigned int highest_expected = 0; ++ unsigned int total_votes = 0; ++ cs_error_t error = CS_OK; ++ ++ log_printf(LOG_LEVEL_DEBUG, "got getinfo request on %p for node %d\n", conn, req_lib_votequorum_getinfo->nodeid); ++ ++ if (req_lib_votequorum_getinfo->nodeid) { ++ node = find_node_by_nodeid(req_lib_votequorum_getinfo->nodeid); ++ } ++ else { ++ node = us; ++ } ++ ++ if (node) { ++ struct cluster_node *iternode; ++ struct list_head *nodelist; ++ ++ list_iterate(nodelist, &cluster_members_list) { ++ iternode = list_entry(nodelist, struct cluster_node, list); ++ ++ if (node->state == NODESTATE_MEMBER) { ++ highest_expected = ++ max(highest_expected, node->expected_votes); ++ total_votes += node->votes; ++ } ++ } ++ ++ if (quorum_device && quorum_device->state == NODESTATE_MEMBER) { ++ total_votes += quorum_device->votes; ++ } ++ ++ res_lib_votequorum_getinfo.votes = us->votes; ++ res_lib_votequorum_getinfo.expected_votes = us->expected_votes; ++ res_lib_votequorum_getinfo.highest_expected = highest_expected; ++ ++ res_lib_votequorum_getinfo.quorum = quorum; ++ res_lib_votequorum_getinfo.total_votes = total_votes; ++ res_lib_votequorum_getinfo.flags = 0; ++ res_lib_votequorum_getinfo.nodeid = node->node_id; ++ ++ if (us->flags & NODE_FLAGS_HASSTATE) ++ res_lib_votequorum_getinfo.flags |= VOTEQUORUM_INFO_FLAG_HASSTATE; ++ if (quorum_flags & VOTEQUORUM_FLAG_FEATURE_TWONODE) ++ res_lib_votequorum_getinfo.flags |= VOTEQUORUM_INFO_FLAG_TWONODE; ++ if (cluster_is_quorate) ++ res_lib_votequorum_getinfo.flags |= VOTEQUORUM_INFO_FLAG_QUORATE; ++ if (us->flags & NODE_FLAGS_SEESDISALLOWED) ++ res_lib_votequorum_getinfo.flags |= VOTEQUORUM_INFO_FLAG_DISALLOWED; ++ } ++ else { ++ error = CS_ERR_NOT_EXIST; ++ } ++ ++ res_lib_votequorum_getinfo.header.size = sizeof(res_lib_votequorum_getinfo); ++ res_lib_votequorum_getinfo.header.id = MESSAGE_RES_VOTEQUORUM_GETINFO; ++ res_lib_votequorum_getinfo.header.error = error; ++ corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_getinfo, sizeof(res_lib_votequorum_getinfo)); ++ log_printf(LOG_LEVEL_DEBUG, "getinfo response error: %d\n", error); ++} ++ ++/* Message from the library */ ++static void message_handler_req_lib_votequorum_setexpected (void *conn, void *message) ++{ ++ struct req_lib_votequorum_setexpected *req_lib_votequorum_setexpected = (struct req_lib_votequorum_setexpected *)message; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ cs_error_t error = CS_OK; ++ unsigned int newquorum; ++ unsigned int total_votes; ++ ++ ENTER(); ++ ++ /* ++ * If there are disallowed nodes, then we can't allow the user ++ * to bypass them by fiddling with expected votes. ++ */ ++ if (quorum_flags & VOTEQUORUM_FLAG_FEATURE_DISALLOWED && have_disallowed()) { ++ error = CS_ERR_EXIST; ++ goto error_exit; ++ } ++ ++ /* Validate new expected votes */ ++ newquorum = calculate_quorum(1, req_lib_votequorum_setexpected->expected_votes, &total_votes); ++ if (newquorum < total_votes / 2 ++ || newquorum > total_votes) { ++ error = CS_ERR_INVALID_PARAM; ++ goto error_exit; ++ } ++ ++ quorum_exec_send_reconfigure(RECONFIG_PARAM_EXPECTED_VOTES, us->node_id, req_lib_votequorum_setexpected->expected_votes); ++ ++ /* send status */ ++error_exit: ++ res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); ++ res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; ++ res_lib_votequorum_status.header.error = error; ++ corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status)); ++ LEAVE(); ++} ++ ++/* Message from the library */ ++static void message_handler_req_lib_votequorum_setvotes (void *conn, void *message) ++{ ++ struct req_lib_votequorum_setvotes *req_lib_votequorum_setvotes = (struct req_lib_votequorum_setvotes *)message; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ struct cluster_node *node; ++ unsigned int newquorum; ++ unsigned int total_votes; ++ unsigned int saved_votes; ++ cs_error_t error = CS_OK; ++ ++ ENTER(); ++ ++ node = find_node_by_nodeid(req_lib_votequorum_setvotes->nodeid); ++ if (!node) { ++ error = CS_ERR_NAME_NOT_FOUND; ++ goto error_exit; ++ } ++ ++ /* Check votes is valid */ ++ saved_votes = node->votes; ++ node->votes = req_lib_votequorum_setvotes->votes; ++ ++ newquorum = calculate_quorum(1, 0, &total_votes); ++ ++ if (newquorum < total_votes / 2 || newquorum > total_votes) { ++ node->votes = saved_votes; ++ error = CS_ERR_INVALID_PARAM; ++ goto error_exit; ++ } ++ ++ if (!req_lib_votequorum_setvotes->nodeid) ++ req_lib_votequorum_setvotes->nodeid = corosync_api->totem_nodeid_get(); ++ ++ quorum_exec_send_reconfigure(RECONFIG_PARAM_NODE_VOTES, req_lib_votequorum_setvotes->nodeid, req_lib_votequorum_setvotes->votes); ++ ++error_exit: ++ /* send status */ ++ res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); ++ res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; ++ res_lib_votequorum_status.header.error = error; ++ corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status)); ++ LEAVE(); ++} ++ ++static void message_handler_req_lib_votequorum_leaving (void *conn, void *message) ++{ ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ cs_error_t error = CS_OK; ++ ++ ENTER(); ++ ++ quorum_exec_send_reconfigure(RECONFIG_PARAM_LEAVING, us->node_id, 0); ++ ++ /* send status */ ++ res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); ++ res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; ++ res_lib_votequorum_status.header.error = error; ++ corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status)); ++ LEAVE(); ++} ++ ++static void quorum_device_timer_fn(void *arg) ++{ ++ struct timeval now; ++ ++ ENTER(); ++ if (!quorum_device || quorum_device->state == NODESTATE_DEAD) ++ return; ++ gettimeofday(&now, NULL); ++ if (quorum_device->last_hello.tv_sec + quorumdev_poll/1000 < now.tv_sec) { ++ quorum_device->state = NODESTATE_DEAD; ++ log_printf(LOG_INFO, "lost contact with quorum device\n"); ++ recalculate_quorum(0); ++ } ++ else { ++ corosync_api->timer_add_duration((unsigned long long)quorumdev_poll*1000000, quorum_device, ++ quorum_device_timer_fn, &quorum_device_timer); ++ } ++ LEAVE(); ++} ++ ++ ++static void message_handler_req_lib_votequorum_qdisk_register (void *conn, void *message) ++{ ++ struct req_lib_votequorum_qdisk_register *req_lib_votequorum_qdisk_register = (struct req_lib_votequorum_qdisk_register *)message; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ cs_error_t error = CS_OK; ++ ++ ENTER(); ++ ++ if (quorum_device) { ++ error = CS_ERR_EXIST; ++ } ++ else { ++ quorum_device = allocate_node(0); ++ quorum_device->state = NODESTATE_DEAD; ++ quorum_device->votes = req_lib_votequorum_qdisk_register->votes; ++ strcpy(quorum_device_name, req_lib_votequorum_qdisk_register->name); ++ list_add(&quorum_device->list, &cluster_members_list); ++ } ++ ++ /* send status */ ++ res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); ++ res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; ++ res_lib_votequorum_status.header.error = error; ++ corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status)); ++ LEAVE(); ++} ++ ++static void message_handler_req_lib_votequorum_qdisk_unregister (void *conn, void *message) ++{ ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ cs_error_t error = CS_OK; ++ ++ ENTER(); ++ ++ if (quorum_device) { ++ struct cluster_node *node = quorum_device; ++ ++ quorum_device = NULL; ++ list_del(&node->list); ++ free(node); ++ recalculate_quorum(0); ++ } ++ else { ++ error = CS_ERR_NOT_EXIST; ++ } ++ ++ /* send status */ ++ res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); ++ res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; ++ res_lib_votequorum_status.header.error = error; ++ corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status)); ++ LEAVE(); ++} ++ ++static void message_handler_req_lib_votequorum_qdisk_poll (void *conn, void *message) ++{ ++ struct req_lib_votequorum_qdisk_poll *req_lib_votequorum_qdisk_poll = (struct req_lib_votequorum_qdisk_poll *)message; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ cs_error_t error = CS_OK; ++ ++ ENTER(); ++ ++ if (quorum_device) { ++ if (req_lib_votequorum_qdisk_poll->state) { ++ gettimeofday(&quorum_device->last_hello, NULL); ++ if (quorum_device->state == NODESTATE_DEAD) { ++ quorum_device->state = NODESTATE_MEMBER; ++ recalculate_quorum(0); ++ ++ corosync_api->timer_add_duration((unsigned long long)quorumdev_poll*1000000, quorum_device, ++ quorum_device_timer_fn, &quorum_device_timer); ++ } ++ } ++ else { ++ if (quorum_device->state == NODESTATE_MEMBER) { ++ quorum_device->state = NODESTATE_DEAD; ++ recalculate_quorum(0); ++ corosync_api->timer_delete(quorum_device_timer); ++ } ++ } ++ } ++ else { ++ error = CS_ERR_NOT_EXIST; ++ } ++ ++ /* send status */ ++ res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); ++ res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; ++ res_lib_votequorum_status.header.error = error; ++ corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status)); ++ ++ LEAVE(); ++} ++ ++static void message_handler_req_lib_votequorum_qdisk_getinfo (void *conn, void *message) ++{ ++ struct res_lib_votequorum_qdisk_getinfo res_lib_votequorum_qdisk_getinfo; ++ cs_error_t error = CS_OK; ++ ++ ENTER(); ++ ++ if (quorum_device) { ++ log_printf(LOG_LEVEL_DEBUG, "got qdisk_getinfo state %d\n", quorum_device->state); ++ res_lib_votequorum_qdisk_getinfo.votes = quorum_device->votes; ++ if (quorum_device->state == NODESTATE_MEMBER) ++ res_lib_votequorum_qdisk_getinfo.state = 1; ++ else ++ res_lib_votequorum_qdisk_getinfo.state = 0; ++ strcpy(res_lib_votequorum_qdisk_getinfo.name, quorum_device_name); ++ } ++ else { ++ error = CS_ERR_NOT_EXIST; ++ } ++ ++ /* send status */ ++ res_lib_votequorum_qdisk_getinfo.header.size = sizeof(res_lib_votequorum_qdisk_getinfo); ++ res_lib_votequorum_qdisk_getinfo.header.id = MESSAGE_RES_VOTEQUORUM_GETINFO; ++ res_lib_votequorum_qdisk_getinfo.header.error = error; ++ corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_qdisk_getinfo, sizeof(res_lib_votequorum_qdisk_getinfo)); ++ ++ LEAVE(); ++} ++ ++static void message_handler_req_lib_votequorum_setstate (void *conn, void *message) ++{ ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ cs_error_t error = CS_OK; ++ ++ ENTER(); ++ ++ us->flags |= NODE_FLAGS_HASSTATE; ++ ++ /* send status */ ++ res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); ++ res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; ++ res_lib_votequorum_status.header.error = error; ++ corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status)); ++ ++ LEAVE(); ++} ++ ++static void message_handler_req_lib_votequorum_trackstart (void *conn, void *msg) ++{ ++ struct req_lib_votequorum_trackstart *req_lib_votequorum_trackstart = (struct req_lib_votequorum_trackstart *)msg; ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn); ++ ++ ENTER(); ++ /* ++ * If an immediate listing of the current cluster membership ++ * is requested, generate membership list ++ */ ++ if (req_lib_votequorum_trackstart->track_flags & CS_TRACK_CURRENT || ++ req_lib_votequorum_trackstart->track_flags & CS_TRACK_CHANGES) { ++ log_printf(LOG_LEVEL_DEBUG, "sending initial status to %p\n", conn); ++ send_quorum_notification(corosync_api->ipc_conn_partner_get (conn), req_lib_votequorum_trackstart->context); ++ } ++ ++ /* ++ * Record requests for tracking ++ */ ++ if (req_lib_votequorum_trackstart->track_flags & CS_TRACK_CHANGES || ++ req_lib_votequorum_trackstart->track_flags & CS_TRACK_CHANGES_ONLY) { ++ ++ quorum_pd->track_flags = req_lib_votequorum_trackstart->track_flags; ++ quorum_pd->tracking_enabled = 1; ++ quorum_pd->tracking_context = req_lib_votequorum_trackstart->context; ++ ++ list_add (&quorum_pd->list, &trackers_list); ++ } ++ ++ /* Send status */ ++ res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); ++ res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; ++ res_lib_votequorum_status.header.error = CS_OK; ++ corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status)); ++ ++ LEAVE(); ++} ++ ++static void message_handler_req_lib_votequorum_trackstop (void *conn, void *msg) ++{ ++ struct res_lib_votequorum_status res_lib_votequorum_status; ++ struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn); ++ int error = CS_OK; ++ ++ ENTER(); ++ ++ if (quorum_pd->tracking_enabled) { ++ error = CS_OK; ++ quorum_pd->tracking_enabled = 0; ++ list_del (&quorum_pd->list); ++ list_init (&quorum_pd->list); ++ } else { ++ error = CS_ERR_NOT_EXIST; ++ } ++ ++ /* send status */ ++ res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); ++ res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; ++ res_lib_votequorum_status.header.error = error; ++ corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status)); ++ ++ LEAVE(); ++} ++ ++ ++static char *kill_reason(int reason) ++{ ++ static char msg[1024]; ++ ++ switch (reason) ++ { ++ case VOTEQUORUM_REASON_KILL_REJECTED: ++ return "our membership application was rejected"; ++ ++ case VOTEQUORUM_REASON_KILL_APPLICATION: ++ return "we were killed by an application request"; ++ ++ case VOTEQUORUM_REASON_KILL_REJOIN: ++ return "we rejoined the cluster without a full restart"; ++ ++ default: ++ sprintf(msg, "we got kill message number %d", reason); ++ return msg; ++ } ++} ++ ++static void reread_config(unsigned int object_handle) ++{ ++ unsigned int old_votes; ++ unsigned int old_expected; ++ ++ old_votes = us->votes; ++ old_expected = us->expected_votes; ++ ++ /* ++ * Reload the configuration ++ */ ++ read_quorum_config(object_handle); ++ ++ /* ++ * Check for fundamental changes that we need to propogate ++ */ ++ if (old_votes != us->votes) { ++ quorum_exec_send_reconfigure(RECONFIG_PARAM_NODE_VOTES, us->node_id, us->votes); ++ } ++ if (old_expected != us->expected_votes) { ++ quorum_exec_send_reconfigure(RECONFIG_PARAM_EXPECTED_VOTES, us->node_id, us->expected_votes); ++ } ++} ++ ++static void quorum_key_change_notify(object_change_type_t change_type, ++ unsigned int parent_object_handle, ++ unsigned int object_handle, ++ void *object_name_pt, int object_name_len, ++ void *key_name_pt, int key_len, ++ void *key_value_pt, int key_value_len, ++ void *priv_data_pt) ++{ ++ if (memcmp(object_name_pt, "quorum", object_name_len) == 0) ++ reread_config(object_handle); ++} ++ ++ ++/* Called when the objdb is reloaded */ ++static void votequorum_objdb_reload_notify( ++ objdb_reload_notify_type_t type, int flush, ++ void *priv_data_pt) ++{ ++ /* ++ * A new quorum {} key might exist, cancel the ++ * existing notification at the start of reload, ++ * and start a new one on the new object when ++ * it's all settled. ++ */ ++ ++ if (type == OBJDB_RELOAD_NOTIFY_START) { ++ corosync_api->object_track_stop( ++ quorum_key_change_notify, ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ } ++ ++ if (type == OBJDB_RELOAD_NOTIFY_END || ++ type == OBJDB_RELOAD_NOTIFY_FAILED) { ++ unsigned int find_handle; ++ unsigned int object_handle; ++ ++ corosync_api->object_find_create(OBJECT_PARENT_HANDLE, "quorum", strlen("quorum"), &find_handle); ++ if (corosync_api->object_find_next(find_handle, &object_handle) == 0) { ++ add_votequorum_config_notification(object_handle); ++ ++ reread_config(object_handle); ++ } ++ else { ++ log_printf(LOG_LEVEL_ERROR, "votequorum objdb tracking stopped, cannot find quorum{} handle in objdb\n"); ++ } ++ } ++} ++ ++ ++static void add_votequorum_config_notification( ++ unsigned int quorum_object_handle) ++{ ++ ++ corosync_api->object_track_start(quorum_object_handle, ++ 1, ++ quorum_key_change_notify, ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ ++ /* ++ * Reload notify must be on the parent object ++ */ ++ corosync_api->object_track_start(OBJECT_PARENT_HANDLE, ++ 1, ++ NULL, ++ NULL, ++ NULL, ++ votequorum_objdb_reload_notify, ++ NULL); ++} diff -Naurd corosync-0.92/test/cpgbench.c corosync-trunk/test/cpgbench.c --- corosync-0.92/test/cpgbench.c 2008-08-15 08:15:26.000000000 +0200 +++ corosync-trunk/test/cpgbench.c 2008-11-06 22:49:07.000000000 +0100 @@ -15036,20 +20418,21 @@ diff -Naurd corosync-0.92/test/logsys_t2.c corosync-trunk/test/logsys_t2.c log_printf(LOG_DEBUG, "If you see this, the logger's busted\n"); diff -Naurd corosync-0.92/test/Makefile corosync-trunk/test/Makefile --- corosync-0.92/test/Makefile 2008-09-25 07:31:42.000000000 +0200 -+++ corosync-trunk/test/Makefile 2008-12-08 16:55:41.000000000 +0100 -@@ -42,9 +42,9 @@ ++++ corosync-trunk/test/Makefile 2009-01-26 11:46:08.000000000 +0100 +@@ -42,9 +42,10 @@ override LDFLAGS += -lnsl -lsocket -lrt endif -LIBRARIES= ../lib/libevs.a ../lib/libcpg.a ../lib/libcfg.a ../lib/libconfdb.a -+LIBRARIES= ../lib/libevs.a ../lib/libcpg.a ../lib/libcfg.a ../lib/libconfdb.a ../lib/libquorum.a ++LIBRARIES= ../lib/libevs.a ../lib/libcpg.a ../lib/libcfg.a ../lib/libconfdb.a ../lib/libquorum.a ../lib/libvotequorum.a LIBS = $(LIBRARIES) -BINARIES= testevs evsbench evsverify testcpg testcpg2 cpgbench testconfdb -+BINARIES= testevs evsbench evsverify testcpg testcpg2 cpgbench testconfdb logsysbench logsysrec testquorum ++BINARIES= testevs evsbench evsverify testcpg testcpg2 cpgbench testconfdb logsysbench logsysrec testquorum \ ++ testvotequorum1 testvotequorum2 override CFLAGS += -I../include override LDFLAGS += -L../lib -@@ -75,12 +75,26 @@ +@@ -75,12 +76,33 @@ testcpg2: testcpg2.o $(LIBRARIES) $(CC) $(LDFLAGS) -o testcpg2 testcpg2.o $(LIBS) @@ -15070,8 +20453,15 @@ diff -Naurd corosync-0.92/test/Makefile corosync-trunk/test/Makefile + +testquorum1: testquorum1.o $(LIBRARIES) + $(CC) $(LDFLAGS) -o testquorum1 testquorum1.o $(LIBS) ++ +testquorum2: testquorum2.o $(LIBRARIES) + $(CC) $(LDFLAGS) -o testquorum2 testquorum2.o $(LIBS) ++ ++testvotequorum1: testvotequorum1.o $(LIBRARIES) ++ $(CC) $(LDFLAGS) -o testvotequorum1 testvotequorum1.o $(LIBS) ++ ++testvotequorum2: testvotequorum2.o $(LIBRARIES) ++ $(CC) $(LDFLAGS) -o testvotequorum2 testvotequorum2.o $(LIBS) + logsys_s: logsys_s.o logsys_s1.o logsys_s2.o ../exec/liblogsys.a $(CC) -o logsys_s logsys_s.o logsys_s1.o logsys_s2.o ../exec/liblogsys.a $(LDFLAGS) @@ -15552,9 +20942,279 @@ diff -Naurd corosync-0.92/test/testquorum.c corosync-trunk/test/testquorum.c + + return 0; +} +diff -Naurd corosync-0.92/test/testvotequorum1.c corosync-trunk/test/testvotequorum1.c +--- corosync-0.92/test/testvotequorum1.c 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/test/testvotequorum1.c 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,159 @@ ++/* ++ * Copyright (c) 2009 Red Hat, Inc. ++ * ++ * All rights reserved. ++ * ++ * Author: Christine Caulfield (ccaulfie@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 CONTIBUTORS "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 ++ ++static votequorum_handle_t handle; ++ ++static char *node_state(int state) ++{ ++ switch (state) { ++ case NODESTATE_JOINING: ++ return "Joining"; ++ break; ++ case NODESTATE_MEMBER: ++ return "Member"; ++ break; ++ case NODESTATE_DEAD: ++ return "Dead"; ++ break; ++ case NODESTATE_LEAVING: ++ return "Leaving"; ++ break; ++ case NODESTATE_DISALLOWED: ++ return "Disallowed"; ++ break; ++ default: ++ return "UNKNOWN"; ++ break; ++ } ++} ++ ++static void votequorum_notification_fn( ++ votequorum_handle_t handle, ++ uint64_t context, ++ uint32_t quorate, ++ uint32_t node_list_entries, ++ votequorum_node_t node_list[] ++ ) ++{ ++ int i; ++ ++ printf("votequorum notification called \n"); ++ printf(" quorate = %d\n", quorate); ++ printf(" number of nodes = %d\n", node_list_entries); ++ ++ for (i = 0; i< node_list_entries; i++) { ++ printf(" %d: %s\n", node_list[i].nodeid, node_state(node_list[i].state)); ++ } ++ printf("\n"); ++} ++ ++ ++int main(int argc, char *argv[]) ++{ ++ struct votequorum_info info; ++ votequorum_callbacks_t callbacks; ++ int err; ++ ++ if (argc > 1 && strcmp(argv[1], "-h")==0) { ++ fprintf(stderr, "usage: %s [new-expected] [new-votes]\n", argv[0]); ++ return 0; ++ } ++ ++ callbacks.votequorum_notify_fn = votequorum_notification_fn; ++ if ( (err=votequorum_initialize(&handle, &callbacks)) != CS_OK) ++ fprintf(stderr, "votequorum_initialize FAILED: %d\n", err); ++ ++ if ( (err = votequorum_trackstart(handle, handle, CS_TRACK_CHANGES)) != CS_OK) ++ fprintf(stderr, "votequorum_trackstart FAILED: %d\n", err); ++ ++ if ( (err=votequorum_getinfo(handle, 0, &info)) != CS_OK) ++ fprintf(stderr, "votequorum_getinfo FAILED: %d\n", err); ++ else { ++ printf("node votes %d\n", info.node_votes); ++ printf("expected votes %d\n", info.node_expected_votes); ++ printf("highest expected %d\n", info.highest_expected); ++ printf("total votes %d\n", info.total_votes); ++ printf("quorum %d\n", info.quorum); ++ printf("flags "); ++ if (info.flags & VOTEQUORUM_INFO_FLAG_HASSTATE) printf("HasState "); ++ if (info.flags & VOTEQUORUM_INFO_FLAG_DISALLOWED) printf("Disallowed "); ++ if (info.flags & VOTEQUORUM_INFO_FLAG_TWONODE) printf("2Node "); ++ if (info.flags & VOTEQUORUM_INFO_FLAG_QUORATE) printf("Quorate "); ++ printf("\n"); ++ } ++ ++ if (argc >= 2 && atoi(argv[1])) { ++ if ( (err=votequorum_setexpected(handle, atoi(argv[1]))) != CS_OK) ++ fprintf(stderr, "set expected votes FAILED: %d\n", err); ++ } ++ if (argc >= 3 && atoi(argv[2])) { ++ if ( (err=votequorum_setvotes(handle, 0, atoi(argv[2]))) != CS_OK) ++ fprintf(stderr, "set votes FAILED: %d\n", err); ++ } ++ ++ if (argc >= 2) { ++ if ( (err=votequorum_getinfo(handle, 0, &info)) != CS_OK) ++ fprintf(stderr, "votequorum_getinfo2 FAILED: %d\n", err); ++ else { ++ printf("-------------------\n"); ++ printf("node votes %d\n", info.node_votes); ++ printf("expected votes %d\n", info.node_expected_votes); ++ printf("highest expected %d\n", info.highest_expected); ++ printf("total votes %d\n", info.total_votes); ++ printf("votequorum %d\n", info.quorum); ++ printf("flags "); ++ if (info.flags & VOTEQUORUM_INFO_FLAG_HASSTATE) printf("HasState "); ++ if (info.flags & VOTEQUORUM_INFO_FLAG_DISALLOWED) printf("Disallowed "); ++ if (info.flags & VOTEQUORUM_INFO_FLAG_TWONODE) printf("2Node "); ++ if (info.flags & VOTEQUORUM_INFO_FLAG_QUORATE) printf("Quorate "); ++ printf("\n"); ++ } ++ } ++ ++ printf("Waiting for votequorum events, press ^C to finish\n"); ++ printf("-------------------\n"); ++ ++ while (1) ++ votequorum_dispatch(handle, CS_DISPATCH_ALL); ++ ++ return 0; ++} +diff -Naurd corosync-0.92/test/testvotequorum2.c corosync-trunk/test/testvotequorum2.c +--- corosync-0.92/test/testvotequorum2.c 1970-01-01 01:00:00.000000000 +0100 ++++ corosync-trunk/test/testvotequorum2.c 2009-01-26 11:46:08.000000000 +0100 +@@ -0,0 +1,96 @@ ++/* ++ * Copyright (c) 2009 Red Hat, Inc. ++ * ++ * All rights reserved. ++ * ++ * Author: Christine Caulfield (ccaulfie@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 CONTIBUTORS "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 ++ ++static votequorum_handle_t handle; ++ ++ ++static void print_info(int ok_to_fail) ++{ ++ struct votequorum_qdisk_info qinfo; ++ int err; ++ ++ if ( (err=votequorum_qdisk_getinfo(handle, &qinfo)) != CS_OK) ++ fprintf(stderr, "votequorum_qdisk_getinfo error %d: %s\n", err, ok_to_fail?"OK":"FAILED"); ++ else { ++ printf("qdisk votes %d\n", qinfo.votes); ++ printf("state %d\n", qinfo.state); ++ printf("name %s\n", qinfo.name); ++ printf("\n"); ++ } ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int pollcount=0, polltime=1; ++ int err; ++ ++ if ( (err=votequorum_initialize(&handle, NULL)) != CS_OK) { ++ fprintf(stderr, "votequorum_initialize FAILED: %d\n", err); ++ return -1; ++ } ++ ++ print_info(1); ++ ++ if (argc >= 2 && atoi(argv[1])) { ++ pollcount = atoi(argv[1]); ++ } ++ if (argc >= 3 && atoi(argv[2])) { ++ polltime = atoi(argv[2]); ++ } ++ ++ if (argc >= 2) { ++ if ( (err=votequorum_qdisk_register(handle, "QDISK", 4)) != CS_OK) ++ fprintf(stderr, "qdisk_register FAILED: %d\n", err); ++ ++ while (pollcount--) { ++ print_info(0); ++ if ((err=votequorum_qdisk_poll(handle, 1)) != CS_OK) ++ fprintf(stderr, "qdisk poll FAILED: %d\n", err); ++ print_info(0); ++ sleep(polltime); ++ } ++ if ((err= votequorum_qdisk_unregister(handle)) != CS_OK) ++ fprintf(stderr, "qdisk unregister FAILED: %d\n", err); ++ } ++ print_info(1); ++ ++ return 0; ++} diff -Naurd corosync-0.92/tools/corosync-cfgtool.c corosync-trunk/tools/corosync-cfgtool.c --- corosync-0.92/tools/corosync-cfgtool.c 2008-08-14 18:54:46.000000000 +0200 -+++ corosync-trunk/tools/corosync-cfgtool.c 2008-11-11 18:25:22.000000000 +0100 ++++ corosync-trunk/tools/corosync-cfgtool.c 2009-01-19 09:31:21.000000000 +0100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2006-2007 Red Hat, Inc. ++ * Copyright (c) 2006-2009 Red Hat, Inc. + * + * All rights reserved. + * @@ -38,6 +38,7 @@ #include #include @@ -15563,12 +21223,13 @@ diff -Naurd corosync-0.92/tools/corosync-cfgtool.c corosync-trunk/tools/corosync #include #include #include -@@ -45,12 +46,12 @@ +@@ -45,12 +46,13 @@ #include #include -#include +#include ++#include #include static void ringstatusget_do (void) @@ -15578,7 +21239,7 @@ diff -Naurd corosync-0.92/tools/corosync-cfgtool.c corosync-trunk/tools/corosync corosync_cfg_handle_t handle; unsigned int interface_count; char **interface_names; -@@ -59,84 +60,160 @@ +@@ -59,84 +61,199 @@ printf ("Printing ring status.\n"); result = corosync_cfg_initialize (&handle, NULL); @@ -15683,7 +21344,7 @@ diff -Naurd corosync-0.92/tools/corosync-cfgtool.c corosync-trunk/tools/corosync + (void)corosync_cfg_finalize (handle); +} + -+void shutdown_callback (corosync_cfg_handle_t cfg_handle, CorosyncCfgShutdownFlagsT flags) ++void shutdown_callback (corosync_cfg_handle_t cfg_handle, corosync_cfg_shutdown_flags_t flags) +{ + printf("shutdown callback called, flags = %d\n",flags); + @@ -15707,12 +21368,12 @@ diff -Naurd corosync-0.92/tools/corosync-cfgtool.c corosync-trunk/tools/corosync +{ + cs_error_t result; + corosync_cfg_handle_t handle; -+ CorosyncCfgCallbacksT callbacks; -+ CorosyncCfgStateNotificationT notificationBuffer; ++ corosync_cfg_callbacks_t callbacks; ++ corosync_cfg_state_notification_t notification_buffer; + pthread_t dispatch_thread; + + printf ("Shutting down corosync\n"); -+ callbacks.corosyncCfgShutdownCallback = shutdown_callback; ++ callbacks.corosync_cfg_shutdown_callback = shutdown_callback; + + result = corosync_cfg_initialize (&handle, &callbacks); + if (result != CS_OK) { @@ -15724,7 +21385,7 @@ diff -Naurd corosync-0.92/tools/corosync-cfgtool.c corosync-trunk/tools/corosync + + result = corosync_cfg_state_track (handle, + 0, -+ ¬ificationBuffer); ++ ¬ification_buffer); + if (result != CS_OK) { + printf ("Could not start corosync cfg tracking error %d\n", result); + exit (1); @@ -15735,6 +21396,45 @@ diff -Naurd corosync-0.92/tools/corosync-cfgtool.c corosync-trunk/tools/corosync + printf ("Could not shutdown (error = %d)\n", result); + } + ++ (void)corosync_cfg_finalize (handle); + } + ++void showaddrs_do(int nodeid) ++{ ++ cs_error_t result; ++ corosync_cfg_handle_t handle; ++ corosync_cfg_callbacks_t callbacks; ++ int numaddrs; ++ int i; ++ corosync_cfg_node_address_t addrs[INTERFACE_MAX]; ++ ++ ++ result = corosync_cfg_initialize (&handle, &callbacks); ++ if (result != CS_OK) { ++ printf ("Could not initialize corosync configuration API error %d\n", result); ++ exit (1); ++ } ++ ++ if (!corosync_cfg_get_node_addrs(handle, nodeid, INTERFACE_MAX, &numaddrs, addrs) == CS_OK) { ++ for (i=0; iss_family == AF_INET6) ++ saddr = &sin6->sin6_addr; ++ else ++ saddr = &sin->sin_addr; ++ ++ inet_ntop(ss->ss_family, saddr, buf, sizeof(buf)); ++ printf("%s", buf); ++ } ++ printf("\n"); ++ } ++ ++ + (void)corosync_cfg_finalize (handle); +} + @@ -15754,27 +21454,28 @@ diff -Naurd corosync-0.92/tools/corosync-cfgtool.c corosync-trunk/tools/corosync + printf ("Could not kill node (error = %d)\n", result); + } + (void)corosync_cfg_finalize (handle); - } - ++} ++ + void usage_do (void) { - printf ("corosync-cfgtool [-s] [-r] [-l] [-u] [service_name] [-v] [version]\n\n"); -+ printf ("corosync-cfgtool [-s] [-r] [-l] [-u] [service_name] [-v] [version] [-k] [nodeid]\n\n"); ++ printf ("corosync-cfgtool [-s] [-r] [-l] [-u] [service_name] [-v] [version] [-k] [nodeid] [-a] [nodeid]\n\n"); printf ("A tool for displaying and configuring active parameters within corosync.\n"); printf ("options:\n"); printf ("\t-s\tDisplays the status of the current rings on this node.\n"); -@@ -144,15 +221,18 @@ +@@ -144,15 +261,19 @@ printf ("\t\tre-enable redundant ring operation.\n"); printf ("\t-l\tLoad a service identified by name.\n"); printf ("\t-u\tUnload a service identified by name.\n"); ++ printf ("\t-a\tDisplay the IP address(es) of a node\n"); + printf ("\t-k\tKill a node identified by node id.\n"); + printf ("\t-h\tShutdown corosync cleanly on this node.\n"); } int main (int argc, char *argv[]) { - const char *options = "srl:u:v:"; -+ const char *options = "srl:u:v:k:h"; ++ const char *options = "srl:u:v:k:a:h"; int opt; int service_load = 0; + unsigned int nodeid; @@ -15786,7 +21487,7 @@ diff -Naurd corosync-0.92/tools/corosync-cfgtool.c corosync-trunk/tools/corosync if (argc == 1) { usage_do (); -@@ -173,17 +253,25 @@ +@@ -173,17 +294,28 @@ service_unload = 1; service = strdup (optarg); break; @@ -15796,6 +21497,9 @@ diff -Naurd corosync-0.92/tools/corosync-cfgtool.c corosync-trunk/tools/corosync + break; + case 'h': + shutdown_do(); ++ break; ++ case 'a': ++ showaddrs_do( atoi(optarg) ); + break; case 'v': version = atoi (optarg); diff --git a/corosync.spec b/corosync.spec index 329deb3..bec5820 100644 --- a/corosync.spec +++ b/corosync.spec @@ -1,14 +1,14 @@ -%define alphatag svn1709 +%define alphatag svn1750 Name: corosync Summary: The Corosync Cluster Engine and Application Programming Interfaces Version: 0.92 -Release: 5%{?alphatag:.%{alphatag}}%{?dist} +Release: 6%{?alphatag:.%{alphatag}}%{?dist} License: BSD Group: System Environment/Base URL: http://www.openais.org Source0: http://developer.osdl.org/dev/openais/downloads/corosync-%{version}/corosync-%{version}.tar.gz -Patch0: corosync-trunk-1709.diff +Patch0: corosync-trunk-1750.diff BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Requires(pre): /usr/sbin/useradd @@ -94,6 +94,7 @@ fi %{_libexecdir}/lcrso/service_evs.lcrso %{_libexecdir}/lcrso/service_confdb.lcrso %{_libexecdir}/lcrso/service_pload.lcrso +%{_libexecdir}/lcrso/service_votequorum.lcrso %{_libexecdir}/lcrso/testquorum.lcrso %{_libexecdir}/lcrso/vsf_quorum.lcrso %{_libexecdir}/lcrso/vsf_ykd.lcrso @@ -105,6 +106,8 @@ fi %{_libdir}/corosync/libtotem_pg.so.* %{_libdir}/corosync/liblogsys.so.* %{_libdir}/corosync/libcoroutil.so.* +%{_libdir}/corosync/libquorum.so.* +%{_libdir}/corosync/libvotequorum.so.* %{_mandir}/man8/corosync_overview.8* %{_mandir}/man8/corosync-objctl.8* %{_mandir}/man5/corosync.conf.5* @@ -125,6 +128,8 @@ fi %{_includedir}/corosync/list.h %{_includedir}/corosync/mar_gen.h %{_includedir}/corosync/swab.h +%{_includedir}/corosync/quorum.h +%{_includedir}/corosync/votequorum.h %dir %{_includedir}/corosync/totem/ %{_includedir}/corosync/totem/coropoll.h %{_includedir}/corosync/totem/totem.h @@ -147,15 +152,23 @@ fi %{_libdir}/corosync/libtotem_pg.so %{_libdir}/corosync/liblogsys.so %{_libdir}/corosync/libcoroutil.so +%{_libdir}/corosync/libquorum.so +%{_libdir}/corosync/libvotequorum.so %{_mandir}/man3/cpg_*3* %{_mandir}/man3/evs_*3* %{_mandir}/man3/confdb_*3* +%{_mandir}/man3/votequorum_*3* %{_mandir}/man8/cpg_overview.8* %{_mandir}/man8/evs_overview.8* %{_mandir}/man8/confdb_overview.8* %{_mandir}/man8/logsys_overview.8* +%{_mandir}/man8/votequorum_overview.8* %changelog +* Tue Jan 27 2009 Fabio M. Di Nitto - 0.92-6.svn1750 +- Update to svn trunk at revision 1750 from upstream. +- Include new quorum service in the packaging. + * Mon Dec 15 2008 Fabio M. Di Nitto - 0.92-5.svn1709 - Update to svn trunk at revision 1709 from upstream. - Update spec file to include new include files.