1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-26 21:57:41 +03:00

vacuum event framework

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Signed-off-by: Wolfgang Mueller-Friedt <wolfmuel@de.ibm.com>

(This used to be ctdb commit 30cdad97706a9e9bb210120699aa939f6b16e8ca)
This commit is contained in:
Ronnie Sahlberg 2009-07-23 16:03:39 +10:00
parent fb63d27e4e
commit 1653af16a6
4 changed files with 221 additions and 0 deletions

View File

@ -54,6 +54,7 @@ CTDB_SERVER_OBJ = server/ctdbd.o server/ctdb_daemon.o server/ctdb_lockwait.o \
server/ctdb_traverse.o server/eventscript.o server/ctdb_takeover.o \
server/ctdb_serverids.o server/ctdb_persistent.o \
server/ctdb_keepalive.o server/ctdb_logging.o server/ctdb_uptime.c \
server/ctdb_vacuum.c \
$(CTDB_CLIENT_OBJ) $(CTDB_TCP_OBJ) @INFINIBAND_WRAPPER_OBJ@
TEST_BINS=tests/bin/ctdb_bench tests/bin/ctdb_fetch tests/bin/ctdb_store \

View File

@ -291,6 +291,14 @@ static int ctdb_local_attach(struct ctdb_context *ctdb, const char *db_name, boo
return -1;
}
ret = ctdb_vacuum_init(ctdb_db);
if (ret != 0) {
DEBUG(DEBUG_CRIT,("Failed to setup vacuuming for database '%s'\n", ctdb_db->db_name));
talloc_free(ctdb_db);
return -1;
}
DEBUG(DEBUG_INFO,("Attached to database '%s'\n", ctdb_db->db_path));
/* success */

View File

@ -56,6 +56,8 @@ static const struct {
{ "RecLockLatencyMs", 1000, offsetof(struct ctdb_tunable, reclock_latency_ms) },
{ "RecoveryDropAllIPs", 60, offsetof(struct ctdb_tunable, recovery_drop_all_ips) },
{ "VerifyRecoveryLock", 1, offsetof(struct ctdb_tunable, verify_recovery_lock) },
{ "VacuumDefaultInterval", 10, offsetof(struct ctdb_tunable, vacuum_default_interval) },
{ "VacuumMaxRunTime", 5, offsetof(struct ctdb_tunable, vacuum_max_run_time) },
};
/*

210
ctdb/server/ctdb_vacuum.c Normal file
View File

@ -0,0 +1,210 @@
/*
ctdb vacuuming events
Copyright (C) Ronnie Sahlberg 2009
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 3 of the License, or
(at your option) any later version.
This program 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, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "lib/events/events.h"
#include "lib/tdb/include/tdb.h"
#include "system/network.h"
#include "system/filesys.h"
#include "system/dir.h"
#include "../include/ctdb_private.h"
#include "db_wrap.h"
#include "lib/util/dlinklist.h"
#include "lib/events/events.h"
#include "../include/ctdb_private.h"
enum vacuum_child_status { VACUUM_RUNNING, VACUUM_OK, VACUUM_ERROR, VACUUM_TIMEOUT};
struct ctdb_vacuum_child_context {
struct ctdb_vacuum_handle *vacuum_handle;
int fd[2];
pid_t child_pid;
enum vacuum_child_status status;
struct timeval start_time;
};
struct ctdb_vacuum_handle {
struct ctdb_db_context *ctdb_db;
struct ctdb_vacuum_child_context *child_ctx;
};
static void ctdb_vacuum_event(struct event_context *ev, struct timed_event *te, struct timeval t, void *private_data);
static int vacuum_child_destructor(struct ctdb_vacuum_child_context *child_ctx)
{
double l = timeval_elapsed(&child_ctx->start_time);
struct ctdb_db_context *ctdb_db = child_ctx->vacuum_handle->ctdb_db;
struct ctdb_context *ctdb = ctdb_db->ctdb;
DEBUG(DEBUG_ERR,("Vacuuming took %.3f seconds for database %s\n", l, ctdb_db->db_name));
if (child_ctx->child_pid != -1) {
kill(child_ctx->child_pid, SIGKILL);
}
/* here calculate a new interval */
/* child_ctx->status */
DEBUG(DEBUG_ERR, ("Start new vacuum event for %s\n", ctdb_db->db_name));
event_add_timed(ctdb->ev, child_ctx->vacuum_handle, timeval_current_ofs(ctdb->tunable.vacuum_default_interval, 0), ctdb_vacuum_event, child_ctx->vacuum_handle);
return 0;
}
/*
* this event is generated when a vacuum child process times out
*/
static void vacuum_child_timeout(struct event_context *ev, struct timed_event *te,
struct timeval t, void *private_data)
{
struct ctdb_vacuum_child_context *child_ctx = talloc_get_type(private_data, struct ctdb_vacuum_child_context);
DEBUG(DEBUG_ERR,("Vacuuming child process timed out for db %s\n", child_ctx->vacuum_handle->ctdb_db->db_name));
child_ctx->status = VACUUM_TIMEOUT;
talloc_free(child_ctx);
}
/*
* this event is generated when a vacuum child process has completed
*/
static void vacuum_child_handler(struct event_context *ev, struct fd_event *fde,
uint16_t flags, void *private_data)
{
struct ctdb_vacuum_child_context *child_ctx = talloc_get_type(private_data, struct ctdb_vacuum_child_context);
char c = 0;
int ret;
DEBUG(DEBUG_ERR,("Vacuuming child finished for db %s\n", child_ctx->vacuum_handle->ctdb_db->db_name));
child_ctx->child_pid = -1;
ret = read(child_ctx->fd[0], &c, 1);
if (ret != 1 || c != 0) {
child_ctx->status = VACUUM_ERROR;
DEBUG(DEBUG_ERR, ("A vacuum child process failed with an error for database %s. ret=%d c=%d\n", child_ctx->vacuum_handle->ctdb_db->db_name, ret, c));
} else {
child_ctx->status = VACUUM_OK;
}
talloc_free(child_ctx);
}
/*
* this event is called every time we need to start a new vacuum process
*/
static void
ctdb_vacuum_event(struct event_context *ev, struct timed_event *te,
struct timeval t, void *private_data)
{
struct ctdb_vacuum_handle *vacuum_handle = talloc_get_type(private_data, struct ctdb_vacuum_handle);
struct ctdb_db_context *ctdb_db = vacuum_handle->ctdb_db;
struct ctdb_context *ctdb = ctdb_db->ctdb;
struct ctdb_vacuum_child_context *child_ctx;
int ret;
DEBUG(DEBUG_ERR,("Start a vacuuming child process for db %s\n", ctdb_db->db_name));
/* we dont vacuum if we are in recovery mode */
if (ctdb->recovery_mode == CTDB_RECOVERY_ACTIVE) {
event_add_timed(ctdb->ev, vacuum_handle, timeval_current_ofs(ctdb->tunable.vacuum_default_interval, 0), ctdb_vacuum_event, vacuum_handle);
return;
}
child_ctx = talloc(vacuum_handle, struct ctdb_vacuum_child_context);
if (child_ctx == NULL) {
DEBUG(DEBUG_CRIT, (__location__ " Failed to allocate child context for vacuuming of %s\n", ctdb_db->db_name));
ctdb_fatal(ctdb, "Out of memory when crating vacuum child context. Shutting down\n");
}
ret = pipe(child_ctx->fd);
if (ret != 0) {
talloc_free(child_ctx);
DEBUG(DEBUG_ERR, ("Failed to create pipe for vacuum child process.\n"));
event_add_timed(ctdb->ev, vacuum_handle, timeval_current_ofs(ctdb->tunable.vacuum_default_interval, 0), ctdb_vacuum_event, vacuum_handle);
return;
}
child_ctx->child_pid = fork();
if (child_ctx->child_pid == (pid_t)-1) {
close(child_ctx->fd[0]);
close(child_ctx->fd[1]);
talloc_free(child_ctx);
DEBUG(DEBUG_ERR, ("Failed to fork vacuum child process.\n"));
event_add_timed(ctdb->ev, vacuum_handle, timeval_current_ofs(ctdb->tunable.vacuum_default_interval, 0), ctdb_vacuum_event, vacuum_handle);
return;
}
if (child_ctx->child_pid == 0) {
char cc = 0;
close(child_ctx->fd[0]);
DEBUG(DEBUG_ERR,("Child process doing vacuuming stuff on db %s\n", ctdb_db->db_name));
write(child_ctx->fd[1], &cc, 1);
_exit(0);
}
set_close_on_exec(child_ctx->fd[0]);
close(child_ctx->fd[1]);
child_ctx->status = VACUUM_RUNNING;
child_ctx->start_time = timeval_current();
talloc_set_destructor(child_ctx, vacuum_child_destructor);
event_add_timed(ctdb->ev, child_ctx,
timeval_current_ofs(ctdb->tunable.vacuum_max_run_time, 0),
vacuum_child_timeout, child_ctx);
event_add_fd(ctdb->ev, child_ctx, child_ctx->fd[0],
EVENT_FD_READ|EVENT_FD_AUTOCLOSE,
vacuum_child_handler,
child_ctx);
vacuum_handle->child_ctx = child_ctx;
child_ctx->vacuum_handle = vacuum_handle;
}
/* this function initializes the vacuuming context for a database
* starts the vacuuming events
*/
int ctdb_vacuum_init(struct ctdb_db_context *ctdb_db)
{
struct ctdb_context *ctdb = ctdb_db->ctdb;
DEBUG(DEBUG_ERR,("Start vacuuming process for database %s\n", ctdb_db->db_name));
ctdb_db->vacuum_handle = talloc(ctdb_db, struct ctdb_vacuum_handle);
CTDB_NO_MEMORY(ctdb, ctdb_db->vacuum_handle);
ctdb_db->vacuum_handle->ctdb_db = ctdb_db;
event_add_timed(ctdb->ev, ctdb_db->vacuum_handle, timeval_current_ofs(ctdb->tunable.vacuum_default_interval, 0), ctdb_vacuum_event, ctdb_db->vacuum_handle);
return 0;
}