*/
#include "includes.h"
-#include "lib/events/events.h"
+#include "lib/tevent/tevent.h"
#include "lib/tdb/include/tdb.h"
#include "system/network.h"
#include "system/filesys.h"
#include "system/wait.h"
+#include "system/shmem.h"
#include "../include/ctdb_private.h"
int LogLevel = DEBUG_NOTICE;
endservent();
address->address = talloc_strdup(mem_ctx, str);
+ CTDB_NO_MEMORY(ctdb, address->address);
+
if (se == NULL) {
address->port = CTDB_PORT;
} else {
*/
uint32_t ctdb_hash(const TDB_DATA *key)
{
- uint32_t value; /* Used to compute the hash value. */
- uint32_t i; /* Used to cycle through random values. */
-
- /* Set the initial value from the key size. */
- for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
- value = (value + (key->dptr[i] << (i*5 % 24)));
-
- return (1103515243 * value + 12345);
+ return tdb_jenkins_hash(discard_const(key));
}
/*
return p;
}
-
-/*
- update a max latency number
- */
-void ctdb_latency(double *latency, struct timeval t)
-{
- double l = timeval_elapsed(&t);
- if (l > *latency) {
- *latency = l;
- }
-}
-
uint32_t ctdb_reqid_new(struct ctdb_context *ctdb, void *state)
{
- uint32_t id;
-
- id = ctdb->idr_cnt++ & 0xFFFF;
- id |= (idr_get_new(ctdb->idr, state, 0xFFFF)<<16);
+ int id = idr_get_new_above(ctdb->idr, state, ctdb->lastid+1, INT_MAX);
+ if (id < 0) {
+ DEBUG(DEBUG_DEBUG, ("Reqid wrap!\n"));
+ id = idr_get_new(ctdb->idr, state, INT_MAX);
+ }
+ ctdb->lastid = id;
return id;
}
{
void *p;
- p = _idr_find_type(ctdb->idr, (reqid>>16)&0xFFFF, type, location);
+ p = _idr_find_type(ctdb->idr, reqid, type, location);
if (p == NULL) {
DEBUG(DEBUG_WARNING, ("Could not find idr:%u\n",reqid));
}
{
int ret;
- ret = idr_remove(ctdb->idr, (reqid>>16)&0xFFFF);
+ ret = idr_remove(ctdb->idr, reqid);
if (ret != 0) {
DEBUG(DEBUG_ERR, ("Removing idr that does not exist\n"));
}
#endif
}
+/*
+ * This function forks a child process and drops the realtime
+ * scheduler for the child process.
+ */
+pid_t ctdb_fork(struct ctdb_context *ctdb)
+{
+ pid_t pid;
+
+ pid = fork();
+ if (pid == 0) {
+ if (ctdb->do_setsched) {
+ ctdb_restore_scheduler(ctdb);
+ }
+ }
+ return pid;
+}
+
void set_nonblocking(int fd)
{
unsigned v;
return true;
}
-static bool parse_ipv6(const char *s, unsigned port, ctdb_sock_addr *saddr)
+static bool parse_ipv6(const char *s, const char *ifaces, unsigned port, ctdb_sock_addr *saddr)
{
saddr->ip6.sin6_family = AF_INET6;
saddr->ip6.sin6_port = htons(port);
return false;
}
+ if (ifaces && IN6_IS_ADDR_LINKLOCAL(&saddr->ip6.sin6_addr)) {
+ if (strchr(ifaces, ',')) {
+ DEBUG(DEBUG_ERR, (__location__ " Link local address %s "
+ "is specified for multiple ifaces %s\n",
+ s, ifaces));
+ return false;
+ }
+ saddr->ip6.sin6_scope_id = if_nametoindex(ifaces);
+ }
+
return true;
}
/*
/* now is this a ipv4 or ipv6 address ?*/
- p = index(s, ':');
- if (p == NULL) {
- ret = parse_ipv4(s, port, &saddr->ip);
- } else {
- ret = parse_ipv6(s, port, saddr);
- }
+ ret = parse_ip(s, NULL, port, saddr);
talloc_free(tmp_ctx);
return ret;
/*
parse an ip
*/
-bool parse_ip(const char *addr, ctdb_sock_addr *saddr)
+bool parse_ip(const char *addr, const char *ifaces, unsigned port, ctdb_sock_addr *saddr)
{
char *p;
bool ret;
/* now is this a ipv4 or ipv6 address ?*/
p = index(addr, ':');
if (p == NULL) {
- ret = parse_ipv4(addr, 0, &saddr->ip);
+ ret = parse_ipv4(addr, port, &saddr->ip);
} else {
- ret = parse_ipv6(addr, 0, saddr);
+ ret = parse_ipv6(addr, ifaces, port, saddr);
}
return ret;
/*
parse a ip/mask pair
*/
-bool parse_ip_mask(const char *str, ctdb_sock_addr *addr, unsigned *mask)
+bool parse_ip_mask(const char *str, const char *ifaces, ctdb_sock_addr *addr, unsigned *mask)
{
TALLOC_CTX *tmp_ctx = talloc_new(NULL);
char *s, *p;
/* now is this a ipv4 or ipv6 address ?*/
- p = index(s, ':');
- if (p == NULL) {
- ret = parse_ipv4(s, 0, &addr->ip);
- } else {
- ret = parse_ipv6(s, 0, addr);
- }
+ ret = parse_ip(s, ifaces, 0, addr);
talloc_free(tmp_ctx);
return ret;
return cip;
}
+unsigned ctdb_addr_to_port(ctdb_sock_addr *addr)
+{
+ switch (addr->sa.sa_family) {
+ case AF_INET:
+ return ntohs(addr->ip.sin_port);
+ break;
+ case AF_INET6:
+ return ntohs(addr->ip6.sin6_port);
+ break;
+ default:
+ DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family %u\n", addr->sa.sa_family));
+ }
+
+ return 0;
+}
void ctdb_block_signal(int signum)
{
sigaddset(&set,signum);
sigprocmask(SIG_UNBLOCK,&set,NULL);
}
+
+struct debug_levels debug_levels[] = {
+ {DEBUG_EMERG, "EMERG"},
+ {DEBUG_ALERT, "ALERT"},
+ {DEBUG_CRIT, "CRIT"},
+ {DEBUG_ERR, "ERR"},
+ {DEBUG_WARNING, "WARNING"},
+ {DEBUG_NOTICE, "NOTICE"},
+ {DEBUG_INFO, "INFO"},
+ {DEBUG_DEBUG, "DEBUG"},
+ {0, NULL}
+};
+
+const char *get_debug_by_level(int32_t level)
+{
+ int i;
+
+ for (i=0; debug_levels[i].description != NULL; i++) {
+ if (debug_levels[i].level == level) {
+ return debug_levels[i].description;
+ }
+ }
+ return "Unknown";
+}
+
+int32_t get_debug_by_desc(const char *desc)
+{
+ int i;
+
+ for (i=0; debug_levels[i].description != NULL; i++) {
+ if (!strcmp(debug_levels[i].description, desc)) {
+ return debug_levels[i].level;
+ }
+ }
+
+ return DEBUG_ERR;
+}
+
+/* we don't lock future pages here; it would increase the chance that
+ * we'd fail to mmap later on. */
+void ctdb_lockdown_memory(struct ctdb_context *ctdb)
+{
+#ifdef HAVE_MLOCKALL
+ /* Extra stack, please! */
+ char dummy[10000];
+ memset(dummy, 0, sizeof(dummy));
+
+ if (ctdb->valgrinding) {
+ return;
+ }
+
+ /* Avoid compiler optimizing out dummy. */
+ mlock(dummy, sizeof(dummy));
+ if (mlockall(MCL_CURRENT) != 0) {
+ DEBUG(DEBUG_WARNING,("Failed to lock memory: %s'\n",
+ strerror(errno)));
+ }
+#endif
+}
+
+const char *ctdb_eventscript_call_names[] = {
+ "init",
+ "setup",
+ "startup",
+ "startrecovery",
+ "recovered",
+ "takeip",
+ "releaseip",
+ "stopped",
+ "monitor",
+ "status",
+ "shutdown",
+ "reload",
+ "updateip",
+ "ipreallocated"
+};