mirror of
https://github.com/schoebel/mars
synced 2025-02-04 06:11:35 +00:00
introduced "marsadm log-delete"
TBD: "marsadm log-purge" TBD: long-term cleanup of symlinks in /mars/todo-global/
This commit is contained in:
parent
6127f1d14c
commit
977e5a3b3a
@ -55,6 +55,7 @@ struct light_class {
|
||||
bool cl_hostcontext;
|
||||
bool cl_serial;
|
||||
int cl_father;
|
||||
light_worker_fn cl_prepare;
|
||||
light_worker_fn cl_forward;
|
||||
light_worker_fn cl_backward;
|
||||
};
|
||||
@ -2406,12 +2407,57 @@ done:
|
||||
return status;
|
||||
}
|
||||
|
||||
static int prepare_delete(void *buf, struct mars_dent *dent)
|
||||
{
|
||||
struct mars_global *global = buf;
|
||||
struct mars_dent *target;
|
||||
struct mars_dent *response;
|
||||
const char *response_path = NULL;
|
||||
int max_serial = 0;
|
||||
|
||||
if (!global || !dent || !dent->new_link) {
|
||||
goto done;
|
||||
}
|
||||
target = _mars_find_dent(global, dent->new_link);
|
||||
if (target) {
|
||||
mars_unlink(dent->new_link);
|
||||
target->d_killme = true;
|
||||
MARS_DBG("target '%s' deleted and marked for removal\n", dent->new_link);
|
||||
} else {
|
||||
MARS_DBG("target '%s' does no longer exist\n", dent->new_link);
|
||||
}
|
||||
|
||||
response_path = path_make("/mars/todo-global/deleted-%s", my_id());
|
||||
if (!response_path) {
|
||||
MARS_ERR("cannot build response path for '%s'\n", dent->new_link);
|
||||
goto done;
|
||||
}
|
||||
response = _mars_find_dent(global, response_path);
|
||||
if (response && response->new_link) {
|
||||
sscanf(response->new_link, "%d", &max_serial);
|
||||
}
|
||||
if (dent->d_serial > max_serial) {
|
||||
char response_val[16];
|
||||
max_serial = dent->d_serial;
|
||||
snprintf(response_val, sizeof(response_val), "%09d", max_serial);
|
||||
mars_symlink(response_val, response_path, NULL, 0);
|
||||
}
|
||||
|
||||
done:
|
||||
brick_string_free(response_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// the order is important!
|
||||
enum {
|
||||
// root element: this must have index 0
|
||||
CL_ROOT,
|
||||
// global todos
|
||||
CL_GLOBAL_TODO,
|
||||
CL_GLOBAL_TODO_DELETE,
|
||||
CL_GLOBAL_TODO_ITEMS,
|
||||
// replacement for DNS in kernelspace
|
||||
CL_IPS,
|
||||
CL_PEERS,
|
||||
@ -2448,6 +2494,32 @@ static const struct light_class light_classes[] = {
|
||||
[CL_ROOT] = {
|
||||
},
|
||||
|
||||
/* Subdirectory for global controlling items...
|
||||
*/
|
||||
[CL_GLOBAL_TODO] = {
|
||||
.cl_name = "todo-global",
|
||||
.cl_len = 11,
|
||||
.cl_type = 'd',
|
||||
.cl_hostcontext = false,
|
||||
.cl_father = CL_ROOT,
|
||||
},
|
||||
/* ... and its contents
|
||||
*/
|
||||
[CL_GLOBAL_TODO_DELETE] = {
|
||||
.cl_name = "delete-",
|
||||
.cl_len = 7,
|
||||
.cl_type = 'l',
|
||||
.cl_serial = true,
|
||||
.cl_father = CL_GLOBAL_TODO,
|
||||
.cl_prepare = prepare_delete,
|
||||
},
|
||||
[CL_GLOBAL_TODO_ITEMS] = {
|
||||
.cl_name = "",
|
||||
.cl_len = 0, // catch any
|
||||
.cl_type = 'l',
|
||||
.cl_father = CL_GLOBAL_TODO,
|
||||
},
|
||||
|
||||
/* Directory containing the addresses of all peers
|
||||
*/
|
||||
[CL_IPS] = {
|
||||
@ -2798,7 +2870,7 @@ done:
|
||||
/* Do some syntactic checks, then delegate work to the real worker functions
|
||||
* from the light_classes[] table.
|
||||
*/
|
||||
static int light_worker(struct mars_global *global, struct mars_dent *dent, bool direction)
|
||||
static int light_worker(struct mars_global *global, struct mars_dent *dent, bool prepare, bool direction)
|
||||
{
|
||||
light_worker_fn worker;
|
||||
int class = dent->d_class;
|
||||
@ -2845,7 +2917,9 @@ static int light_worker(struct mars_global *global, struct mars_dent *dent, bool
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
if (direction) {
|
||||
if (prepare) {
|
||||
worker = light_classes[class].cl_prepare;
|
||||
} else if (direction) {
|
||||
worker = light_classes[class].cl_backward;
|
||||
} else {
|
||||
worker = light_classes[class].cl_forward;
|
||||
|
@ -57,10 +57,11 @@ struct mars_global {
|
||||
int global_version;
|
||||
};
|
||||
|
||||
typedef int (*mars_dent_checker)(struct mars_dent *parent, const char *name, int namlen, unsigned int d_type, int *prefix, int *serial);
|
||||
typedef int (*mars_dent_worker)(struct mars_global *global, struct mars_dent *dent, bool direction);
|
||||
typedef int (*mars_dent_checker_fn)(struct mars_dent *parent, const char *name, int namlen, unsigned int d_type, int *prefix, int *serial);
|
||||
typedef int (*mars_dent_worker_fn)(struct mars_global *global, struct mars_dent *dent, bool prepare, bool direction);
|
||||
|
||||
extern int mars_dent_work(struct mars_global *global, char *dirname, int allocsize, mars_dent_checker checker, mars_dent_worker worker, void *buf, int maxdepth);
|
||||
extern int mars_dent_work(struct mars_global *global, char *dirname, int allocsize, mars_dent_checker_fn checker, mars_dent_worker_fn worker, void *buf, int maxdepth);
|
||||
extern struct mars_dent *_mars_find_dent(struct mars_global *global, const char *path);
|
||||
extern struct mars_dent *mars_find_dent(struct mars_global *global, const char *path);
|
||||
extern int mars_find_dent_all(struct mars_global *global, char *prefix, struct mars_dent ***table);
|
||||
extern void mars_kill_dent(struct mars_dent *dent);
|
||||
@ -112,6 +113,7 @@ extern struct mars_brick *make_brick_all(
|
||||
*/
|
||||
extern int mars_stat(const char *path, struct kstat *stat, bool use_lstat);
|
||||
extern int mars_mkdir(const char *path);
|
||||
extern int mars_unlink(const char *path);
|
||||
extern int mars_symlink(const char *oldpath, const char *newpath, const struct timespec *stamp, uid_t uid);
|
||||
extern int mars_rename(const char *oldpath, const char *newpath);
|
||||
extern int mars_chmod(const char *path, mode_t mode);
|
||||
|
@ -96,6 +96,20 @@ int mars_mkdir(const char *path)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mars_mkdir);
|
||||
|
||||
int mars_unlink(const char *path)
|
||||
{
|
||||
mm_segment_t oldfs;
|
||||
int status;
|
||||
|
||||
oldfs = get_fs();
|
||||
set_fs(get_ds());
|
||||
status = sys_unlink(path);
|
||||
set_fs(oldfs);
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mars_unlink);
|
||||
|
||||
int mars_symlink(const char *oldpath, const char *newpath, const struct timespec *stamp, uid_t uid)
|
||||
{
|
||||
char *tmp = backskip_replace(newpath, '/', true, "/.tmp-");
|
||||
@ -270,7 +284,7 @@ EXPORT_SYMBOL_GPL(mars_power_button_recursive);
|
||||
|
||||
struct mars_cookie {
|
||||
struct mars_global *global;
|
||||
mars_dent_checker checker;
|
||||
mars_dent_checker_fn checker;
|
||||
char *path;
|
||||
struct mars_dent *parent;
|
||||
int pathlen;
|
||||
@ -479,7 +493,7 @@ static int _mars_readdir(struct mars_cookie *cookie)
|
||||
return status;
|
||||
}
|
||||
|
||||
int mars_dent_work(struct mars_global *global, char *dirname, int allocsize, mars_dent_checker checker, mars_dent_worker worker, void *buf, int maxdepth)
|
||||
int mars_dent_work(struct mars_global *global, char *dirname, int allocsize, mars_dent_checker_fn checker, mars_dent_worker_fn worker, void *buf, int maxdepth)
|
||||
{
|
||||
static int version = 0;
|
||||
struct mars_cookie cookie = {
|
||||
@ -555,6 +569,20 @@ restart:
|
||||
goto restart;
|
||||
}
|
||||
|
||||
/* Preparation pass.
|
||||
* Here is a chance to mark some dents for removal
|
||||
* (or other types of non-destructive operations)
|
||||
*/
|
||||
for (tmp = global->dent_anchor.next, next = tmp->next; tmp != &global->dent_anchor; tmp = next, next = next->next) {
|
||||
struct mars_dent *dent = container_of(tmp, struct mars_dent, dent_link);
|
||||
msleep(10); // yield
|
||||
MARS_IO("forward prepare '%s'\n", dent->d_path);
|
||||
status = worker(buf, dent, true, false);
|
||||
if (status)
|
||||
MARS_IO("forward treat '%s' status = %d\n", dent->d_path, status);
|
||||
total_status |= status;
|
||||
}
|
||||
|
||||
/* Remove all dents marked for removal.
|
||||
*/
|
||||
for (tmp = global->dent_anchor.next, next = tmp->next; tmp != &global->dent_anchor; tmp = next, next = next->next) {
|
||||
@ -576,7 +604,7 @@ restart:
|
||||
up_read(&global->dent_mutex);
|
||||
msleep(10); // yield
|
||||
MARS_IO("forward treat '%s'\n", dent->d_path);
|
||||
status = worker(buf, dent, false);
|
||||
status = worker(buf, dent, false, false);
|
||||
if (status)
|
||||
MARS_IO("forward treat '%s' status = %d\n", dent->d_path, status);
|
||||
down_read(&global->dent_mutex);
|
||||
@ -590,7 +618,7 @@ restart:
|
||||
up_read(&global->dent_mutex);
|
||||
msleep(10); // yield
|
||||
MARS_IO("backward treat '%s'\n", dent->d_path);
|
||||
status = worker(buf, dent, true);
|
||||
status = worker(buf, dent, false, true);
|
||||
if (status)
|
||||
MARS_IO("backward treat '%s' status = %d\n", dent->d_path, status);
|
||||
down_read(&global->dent_mutex);
|
||||
@ -607,7 +635,6 @@ done:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mars_dent_work);
|
||||
|
||||
static
|
||||
struct mars_dent *_mars_find_dent(struct mars_global *global, const char *path)
|
||||
{
|
||||
struct mars_dent *res = NULL;
|
||||
@ -627,7 +654,7 @@ struct mars_dent *_mars_find_dent(struct mars_global *global, const char *path)
|
||||
|
||||
return res;
|
||||
}
|
||||
//EXPORT_SYMBOL_GPL(_mars_find_dent);
|
||||
EXPORT_SYMBOL_GPL(_mars_find_dent);
|
||||
|
||||
struct mars_dent *mars_find_dent(struct mars_global *global, const char *path)
|
||||
{
|
||||
|
@ -229,6 +229,7 @@ sub _create_cluster {
|
||||
system("mkdir $mars/ips") unless -d "$mars/ips";
|
||||
system("mkdir $mars/defaults") unless -d "$mars/defaults";
|
||||
system("mkdir $mars/defaults-$host") unless -d "$mars/defaults-$host";
|
||||
system("mkdir $mars/todo-global") unless -d "$mars/todo-global";
|
||||
symlink($ip, "$mars/ips/ip-$host");
|
||||
}
|
||||
|
||||
@ -375,6 +376,46 @@ sub logrotate_res {
|
||||
system("touch $next");
|
||||
}
|
||||
|
||||
sub _allowed_logdelete {
|
||||
my ($cmd, $res) = @_;
|
||||
my $max = -1;
|
||||
my @paths = glob("$mars/resource-$res/replay-*") or die "cannot find any replay symlinks\n";
|
||||
foreach my $path (@paths) {
|
||||
my $target = readlink($path) or die "cannot read symlink '$path'\n";
|
||||
my $nr = $target;
|
||||
$nr =~ s/^.*log-([0-9]+)-.+$/$1/;
|
||||
$max = $nr if $nr > $max;
|
||||
}
|
||||
return $max;
|
||||
}
|
||||
|
||||
sub _create_delete {
|
||||
my ($target) = @_;
|
||||
my $nr = 0;
|
||||
my @paths = glob("$mars/todo-global/delete-*");
|
||||
if(@paths) {
|
||||
my $last = pop(@paths);
|
||||
$nr = $last;
|
||||
$nr =~ s/^.*delete-([0-9]+)$/$1/;
|
||||
}
|
||||
my $new = sprintf("$mars/todo-global/delete-%09d", $nr + 1);
|
||||
print "create symlink $new -> $target\n";
|
||||
symlink($target, $new);
|
||||
}
|
||||
|
||||
sub logdelete_res {
|
||||
my ($cmd, $res) = @_;
|
||||
my @paths = glob("$mars/resource-$res/log-*-$host") or die "cannot find any logfiles\n";
|
||||
@paths = sort(@paths);
|
||||
my $first = shift(@paths);
|
||||
print "chosen '$first' for deletion\n";
|
||||
my $nr = $first;
|
||||
$nr =~ s/^.*log-([0-9]+)-.+$/$1/;
|
||||
my $max = _allowed_logdelete(@_);
|
||||
die "only logfile numbers smaller than $max are allowed to be deleted\n" unless $nr < $max;
|
||||
_create_delete($first);
|
||||
}
|
||||
|
||||
sub attach_res {
|
||||
my ($cmd, $res) = @_;
|
||||
my $detach = ($cmd eq "detach");
|
||||
@ -523,6 +564,9 @@ my %cmd_table =
|
||||
"create-resource" => \&create_res,
|
||||
"join-resource" => \&create_res,
|
||||
"logrotate" => \&logrotate_res,
|
||||
"log-rotate" => \&logrotate_res,
|
||||
"logdelete" => \&logdelete_res,
|
||||
"log-delete" => \&logdelete_res,
|
||||
"fake-sync" => \&fake_local_res,
|
||||
|
||||
# compatible keywords
|
||||
|
Loading…
Reference in New Issue
Block a user