Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F2823000
inline-fn.h
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
inline-fn.h
View Options
/*
* Copyright (C) 2013-2014 Philipp Marek <philipp.marek@linbit.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This software 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _INLINE_FN_H
#define _INLINE_FN_H
#include <time.h>
#include <sys/time.h>
#include <assert.h>
#include <string.h>
#include "timer.h"
#include "config.h"
#include "transport.h"
inline static int get_local_id(void)
{
return local ? local->site_id : -1;
}
inline static uint32_t get_node_id(struct booth_site *node)
{
return node ? node->site_id : 0;
}
/** Returns number of seconds left, if any. */
inline static int term_time_left(struct ticket_config *tk)
{
int left = 0;
if (is_time_set(&tk->term_expires)) {
left = time_left(&tk->term_expires);
}
return (left < 0) ? 0 : left;
}
inline static int leader_and_valid(struct ticket_config *tk)
{
if (tk->leader != local)
return 0;
return term_time_left(tk);
}
/** Is this some leader? */
inline static int is_owned(const struct ticket_config *tk)
{
return (tk->leader && tk->leader != no_leader);
}
inline static int is_resend(struct ticket_config *tk)
{
timetype now;
get_time(&now);
return time_sub_int(&now, &tk->req_sent_at) >= tk->timeout;
}
static inline void init_header_bare(struct boothc_header *h) {
timetype now;
assert(local && local->site_id);
h->magic = htonl(BOOTHC_MAGIC);
h->version = htonl(BOOTHC_VERSION);
h->from = htonl(local->site_id);
if (is_auth_req()) {
get_time(&now);
h->opts = htonl(BOOTH_OPT_AUTH);
h->secs = htonl(secs_since_epoch(&now));
h->usecs = htonl(get_usecs(&now));
} else {
h->opts = htonl(0);
h->secs = htonl(0);
h->usecs = htonl(0);
}
}
/* get the _real_ message length out of the header
*/
#define sendmsglen(msg) ntohl((msg)->header.length)
static inline void init_header(struct boothc_header *h,
int cmd, int request, int options,
int result, int reason, int data_len)
{
init_header_bare(h);
h->length = htonl(data_len -
(is_auth_req() ? 0 : sizeof(struct hmac)));
h->cmd = htonl(cmd);
h->request = htonl(request);
h->options = htonl(options);
h->result = htonl(result);
h->reason = htonl(reason);
}
#define my_last_term(tk) \
(((tk)->state == ST_CANDIDATE && (tk)->last_valid_tk) ? \
(tk)->last_valid_tk->current_term : (tk)->current_term)
extern int TIME_RES, TIME_MULT;
#define msg_term_time(msg) \
ntohl((msg)->ticket.term_valid_for)*TIME_RES/TIME_MULT
#define set_msg_term_time(msg, tk) \
(msg)->ticket.term_valid_for = htonl(term_time_left(tk)*TIME_MULT/TIME_RES)
static inline void init_ticket_msg(struct boothc_ticket_msg *msg,
int cmd, int request, int rv, int reason,
struct ticket_config *tk)
{
assert(sizeof(msg->ticket.id) == sizeof(tk->name));
init_header(&msg->header, cmd, request, 0, rv, reason, sizeof(*msg));
if (!tk) {
memset(&msg->ticket, 0, sizeof(msg->ticket));
} else {
memcpy(msg->ticket.id, tk->name, sizeof(msg->ticket.id));
msg->ticket.leader = htonl(get_node_id(
(tk->leader && tk->leader != no_leader) ? tk->leader :
(tk->voted_for ? tk->voted_for : no_leader)));
msg->ticket.term = htonl(tk->current_term);
set_msg_term_time(msg, tk);
}
}
static inline struct booth_transport const *transport(void)
{
return booth_transport + booth_conf->proto;
}
static inline const char *site_string(struct booth_site *site)
{
return site ? site->addr_string : "NONE";
}
static inline const char *ticket_leader_string(struct ticket_config *tk)
{
return site_string(tk->leader);
}
/* We allow half of the uint32_t to be used;
* half of that below, half of that above the current known "good" value.
* 0 UINT32_MAX
* |--------------------------+----------------+------------|
* | | |
* |--------+-------| allowed range
* |
* current commit index
*
* So, on overflow it looks like that:
* UINT32_MAX 0
* |--------------------------+-----------||---+------------|
* | | |
* |--------+-------| allowed range
* |
* current commit index
*
* This should be possible by using the same datatype and relying
* on the under/overflow semantics.
*
*
* Having 30 bits available, and assuming an expire time of
* one minute and a (high) commit index step of 64 == 2^6 (because
* of weights), we get 2^24 minutes of range - which is ~750
* years. "Should be enough for everybody."
*/
static inline int index_is_higher_than(uint32_t c_high, uint32_t c_low)
{
uint32_t diff;
if (c_high == c_low)
return 0;
diff = c_high - c_low;
if (diff < UINT32_MAX/4)
return 1;
diff = c_low - c_high;
if (diff < UINT32_MAX/4)
return 0;
assert(!"commit index out of range - invalid");
}
static inline uint32_t index_max2(uint32_t a, uint32_t b)
{
return index_is_higher_than(a, b) ? a : b;
}
static inline uint32_t index_max3(uint32_t a, uint32_t b, uint32_t c)
{
return index_max2( index_max2(a, b), c);
}
/* only invoked when ticket leader */
static inline void get_next_election_time(struct ticket_config *tk, timetype *next)
{
assert(tk->leader == local);
/* if last_renewal is not set, which is unusual, it may mean
* that the ticket never got updated, i.e. nobody acked
* ticket updates (say, due to a temporary connection
* problem)
* we may try a bit later again */
if (!is_time_set(&tk->last_renewal)) {
time_reset(next);
} else {
interval_add(&tk->last_renewal, tk->renewal_freq, next);
}
/* if delay_commit is earlier than next, then set next to
* delay_commit */
if (is_time_set(&tk->delay_commit) &&
time_cmp(next, &tk->delay_commit, >)) {
copy_time(&tk->delay_commit, next);
}
}
static inline void expect_replies(struct ticket_config *tk,
int reply_type)
{
tk->retry_number = 0;
tk->acks_expected = reply_type;
tk->acks_received = local->bitmask;
get_time(&tk->req_sent_at);
}
static inline void no_resends(struct ticket_config *tk)
{
tk->retry_number = 0;
tk->acks_expected = 0;
}
static inline struct booth_site *my_vote(struct ticket_config *tk)
{
return tk->votes_for[ local->index ];
}
static inline int count_bits(uint64_t val) {
return __builtin_popcount(val);
}
static inline int majority_of_bits(struct ticket_config *tk, uint64_t val)
{
/* Use ">" to get majority decision, even for an even number
* of participants. */
return count_bits(val) * 2 >
booth_conf->site_count;
}
static inline int all_replied(struct ticket_config *tk)
{
return !(tk->acks_received ^ booth_conf->all_bits);
}
static inline int all_sites_replied(struct ticket_config *tk)
{
return !((tk->acks_received & booth_conf->sites_bits) ^ booth_conf->sites_bits);
}
#endif
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sat, Jan 25, 7:00 AM (1 d, 15 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1212164
Default Alt Text
inline-fn.h (7 KB)
Attached To
Mode
rB Booth
Attached
Detach File
Event Timeline
Log In to Comment