mirror of https://github.com/sipwise/heartbeat.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
209 lines
7.4 KiB
209 lines
7.4 KiB
/*
|
|
* Process tracking object.
|
|
*
|
|
* Copyright (c) 2007 Alan Robertson
|
|
* Author: Alan Robertson <alanr@unix.sh>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
|
|
#ifndef _REPLYTRACK_H
|
|
# define _REPLYTRACK_H
|
|
#include <sys/types.h>
|
|
#include <sys/times.h>
|
|
#include <clplumbing/longclock.h>
|
|
#include <clplumbing/cl_uuid.h>
|
|
|
|
/*
|
|
* We track replies - so we can tell when all expected replies were received.
|
|
*
|
|
* There is a problem in clusters where a message is sent to each node, and a
|
|
* reply is expected from each node of knowing when all the replies have been
|
|
* received.
|
|
*
|
|
* If all nodes are up, it's easy to see when all replies are received.
|
|
* But, if some nodes are down, we really don't want to wait for a timeout
|
|
* before we decide that we've gotten all the replies we're going to get,
|
|
* since nodes can be down for potentially very long periods of time, and
|
|
* waiting for a long timeout can delay things a great deal again and
|
|
* again - causing significant delays and user frustration.
|
|
*
|
|
* That's where these functions come in!
|
|
* Instead, inform these functions what nodes are up and what ones are down,
|
|
* and when you receive a reply, and it will tell you when you've gotten
|
|
* them all - managing all that tedious bookwork for you.
|
|
*/
|
|
|
|
typedef enum _replytrack_completion_type replytrack_completion_type_t;
|
|
typedef enum _nodetrack_change nodetrack_change_t;
|
|
typedef struct _replytrack replytrack_t;
|
|
typedef struct _nodetrack nodetrack_t;
|
|
typedef struct _nodetrack_intersection nodetrack_intersection_t;
|
|
|
|
/*
|
|
* The levels of logging possible for our process
|
|
*/
|
|
enum _replytrack_completion_type {
|
|
REPLYT_ALLRCVD = 2, /* All replies received */
|
|
REPLYT_TIMEOUT, /* Timeout occurred with replies missing */
|
|
};
|
|
|
|
|
|
typedef void (*replytrack_callback_t)
|
|
( replytrack_t * rl
|
|
, gpointer user_data
|
|
, replytrack_completion_type_t reason);
|
|
|
|
typedef void (*replytrack_iterator_t)
|
|
( replytrack_t* rl
|
|
, gpointer user_data
|
|
, const char* node
|
|
, cl_uuid_t uuid);
|
|
|
|
typedef void (*nodetrack_iterator_t)
|
|
( nodetrack_t* rl
|
|
, gpointer user_data
|
|
, const char* node
|
|
, cl_uuid_t uuid);
|
|
|
|
|
|
/*
|
|
* Note:
|
|
* If you use the timeout feature of this code, it relies on you using glib mainloop
|
|
* for your scheduling. timeout_ms should be zero for no timeout.
|
|
*/
|
|
replytrack_t* replytrack_new(nodetrack_t* membership
|
|
, replytrack_callback_t callback
|
|
, unsigned long timeout_ms
|
|
, gpointer user_data);
|
|
|
|
void replytrack_del(replytrack_t *rl);
|
|
gboolean replytrack_gotreply(replytrack_t *rl
|
|
, const char * node
|
|
, cl_uuid_t uuid);
|
|
/* Returns TRUE if this was the final expected reply */
|
|
/*
|
|
* Iterate over the set of outstanding replies:
|
|
* return count of how many items in the iteration
|
|
*/
|
|
int replytrack_outstanding_iterate(replytrack_t* rl
|
|
, replytrack_iterator_t i, gpointer user_data);
|
|
int replytrack_outstanding_count(replytrack_t* rl);
|
|
|
|
/*
|
|
* The functions above operate using a view of membership which is established
|
|
* through the functions below.
|
|
*
|
|
* This can either be through the heartbeat low-level membership API, or any
|
|
* other view of membership you wish. Mentioning a node as either up or down
|
|
* will automatically add that node to our view of potential membership.
|
|
*
|
|
* These functions only support one view of membership per process.
|
|
*
|
|
* The general idea of how to use these functions:
|
|
* Initially:
|
|
* 1) iterate through init membership and call nodetrack_node(up|down) for
|
|
* each node to start things off.
|
|
*
|
|
* On an ongoing basis:
|
|
* 2) call nodetrack_node_up whenever a node comes up
|
|
* We expect a reply from nodes that are up.
|
|
* 3) call nodetrack_node_down whenever a node goes down
|
|
* We don't expect a reply from nodes that are down.
|
|
*
|
|
* For each set of replies you want tracked:
|
|
* 4) Create a replytrack_t for a set of expected replies
|
|
* 5) call replytrack_gotreply() each time you get an expected reply
|
|
* 6) replist_gotreply() returns TRUE when the final message was received.
|
|
* (it does this by comparing against the membership as defined below)
|
|
* 7) you will get a callback when timeout occurs or final message is received
|
|
* n. b.:
|
|
* No callback function => manage timeouts yourself
|
|
* 8) call replytrack_del() when you're done with the reply list
|
|
* n. b.:
|
|
* If you have replies outstanding, and you have a timeout and
|
|
* a callback function set, you will get a warning for destroying
|
|
* a replytrack_t object 'prematurely'.
|
|
* You will also log a warning if you call replytrack_gotreply() after
|
|
* all replies were received or a timeout occurred.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* The levels of logging possible for our process
|
|
*/
|
|
enum _nodetrack_change {
|
|
NODET_UP = 2, /* This node came up */
|
|
NODET_DOWN, /* This node went down */
|
|
};
|
|
|
|
typedef void (*nodetrack_callback_t)
|
|
( nodetrack_t * mbr
|
|
, const char * node
|
|
, cl_uuid_t u
|
|
, nodetrack_change_t reason
|
|
, gpointer user_data);
|
|
|
|
nodetrack_t* nodetrack_new(nodetrack_callback_t callback
|
|
, gpointer user_data);
|
|
void nodetrack_del(nodetrack_t*);
|
|
gboolean nodetrack_nodeup(nodetrack_t* mbr, const char * node
|
|
, cl_uuid_t u);
|
|
gboolean nodetrack_nodedown(nodetrack_t* mbr, const char * node
|
|
, cl_uuid_t u);
|
|
gboolean nodetrack_ismember(nodetrack_t* mbr, const char * node
|
|
, cl_uuid_t u);
|
|
int nodetrack_iterate(nodetrack_t* mbr
|
|
, nodetrack_iterator_t i, gpointer user_data);
|
|
|
|
/* An intesection nodetrack table
|
|
* A node is put into the "intersection" nodetrack_t table when it is in all
|
|
* the underlying constituent nodetrack_t tables, and removed when it is
|
|
* removed from any of them.
|
|
* Note that you can set a callback to be informed when these "intersection"
|
|
* membership changes occur.
|
|
*/
|
|
nodetrack_intersection_t*
|
|
nodetrack_intersection_new(nodetrack_t** tables, int ntables
|
|
, nodetrack_callback_t callback, gpointer user_data);
|
|
void nodetrack_intersection_del(nodetrack_intersection_t*);
|
|
nodetrack_t* nodetrack_intersection_table(nodetrack_intersection_t*);
|
|
|
|
#if 0
|
|
/*
|
|
* I don't know if this should be in this library, or just in
|
|
* the CCM. Probably only the CCM _should_ be using it (when I write it)
|
|
*/
|
|
/*
|
|
* Use of the nodetrack_hb_* functions implies you're using the heartbeat
|
|
* peer-connectivity information as your source of information. This is
|
|
* really only suitable if you're using heartbeat's low-level group membership
|
|
* for your source of who to expect replies from.
|
|
* If you're using nodetrack_hb_init, this replaces step (1) above.
|
|
*/
|
|
void nodetrack_hb_init(void)
|
|
/*
|
|
* If you're using nodetrack_hb_statusmsg, just pass it all status messages
|
|
* and all peer-connectivity status messages or even all heartbeat messages
|
|
* (non-status messages will be ignored).
|
|
* This replaces steps (2) and (3) above _if_ you're using heartbeat low
|
|
* level membership for your source of who to expect replies from.
|
|
*/
|
|
void nodetrack_hb_statusmsg(struct ha_msg* statusmsg);
|
|
#endif /*0*/
|
|
|
|
#endif
|