Roxen.git
/
server
/
base_server
/
fsgc.pike
version
»
Context lines:
10
20
40
80
file
none
3
Roxen.git/server/base_server/fsgc.pike:43:
int num_files; int total_size; string modid; string root; int max_age; int max_files; int max_size;
+
int(0..1) cleanup_parent_dirs;
+
mapping(string:object) handle_lookup = ([]); ADT.Priority_queue pending_gc = ADT.Priority_queue(); //! If set, move files to this directory instead of deleting them. //! //! If set to @[root] or @expr{""@} keep the files as is. string quarantine;
-
+
Configuration owner_mod_conf;
+
+
protected void log_remove(string path, string op)
+
{
+
if (!owner_mod_conf) {
+
if (RoxenModule mod = Roxen.get_module(modid))
+
owner_mod_conf = mod->my_configuration();
+
}
+
if (owner_mod_conf)
+
owner_mod_conf->log_event("fsgc", op, path, ([ ]) );
+
}
+
+
protected int rm_and_parent_cleanup(string path, int(0..1) is_quarantined)
+
{
+
// Make path canonic to avoid visit a leaf directory twice
+
path = canonic_path(path);
+
+
// It's acceptable if the delete fails for a quarantined file that we
+
// just moved using mv(). We can still perform parent dir cleanup if
+
// necessary.
+
int res = predef::rm(path);
+
if (res || is_quarantined) {
+
log_remove(path, is_quarantined ? "quarantined-file" : "delete-file");
+
+
if (cleanup_parent_dirs) {
+
while (1) {
+
// Traverse upward. This gives the parent directory without
+
// trailing slash. The root it already canonic (i.e. no trailing
+
// slash) so the prefix check ensures we're still below the root.
+
path = dirname(path);
+
if (!has_prefix(path, root + "/"))
+
break;
+
+
// Attempt to delete directory and stop if not successful
+
if (!predef::rm(path))
+
break;
+
}
+
}
+
}
+
return res;
+
}
+
protected int rm(string path) { GC_WERR("FSGC: Zap %O\n", path); if (quarantine) { if ((quarantine == root) || (quarantine == "")) return 0;
-
if (!has_prefix(path, root)) return 0;
+
if (!has_prefix(path, root
+ "/"
)) return 0;
string rel = path[sizeof(root)..]; // First try the trivial case.
-
if (mv(path, quarantine + rel)) return 1;
+
if (mv(path, quarantine + rel))
{
+
rm_and_parent_cleanup(path, 1);
+
return 1;
+
}
string dirs = dirname(rel); if (sizeof(dirs)) { if (Stdio.mkdirhier(quarantine + dirs)) { // Try again with the directory existing.
-
if (mv(path, quarantine + rel)) return 1;
+
if (mv(path, quarantine + rel))
{
+
rm_and_parent_cleanup(path, 1);
+
return 1;
} }
-
+
}
// Different filesystems? if (Stdio.cp(path, quarantine + rel)) {
-
return
predef::
rm(path);
+
return rm
_and_parent_cleanup
(path
, 1
);
} werror("FSGC: Failed to copy file %O to %O: %s.\n", path, quarantine + rel, strerror(errno())); return 0; } else {
-
return
predef::
rm(path);
+
return rm
_and_parent_cleanup
(path
, 0
);
} } void check_threshold() { GC_WERR("FSGC: Checking thresholds...\n" " total_size: %d max_size: %d\n" " num_files: %d max_files: %d\n", total_size, max_size, num_files, max_files);
Roxen.git/server/base_server/fsgc.pike:327:
check_threshold(); } } } constant DefaultMonitor = Monitor; protected void create(string modid, string path, int max_age, int|void max_size, int|void max_files,
-
string|void quarantine)
+
string|void quarantine
,
+
int(0..1
)
|void cleanup_parent_dirs)
{ GC_WERR("FSGC: Max age: %d\n", max_age); GC_WERR("FSGC: Max size: %d\n", max_size); GC_WERR("FSGC: Max files: %d\n", max_files); this_program::modid = modid;
-
+
this_program::cleanup_parent_dirs = cleanup_parent_dirs;
this_program::max_age = max_age; this_program::max_size = max_size; this_program::max_files = max_files; root = canonic_path(path); if (quarantine) { if (sizeof(quarantine)) { quarantine = canonic_path(quarantine);
Roxen.git/server/base_server/fsgc.pike:481:
void reconfigure(int max_age, int|void max_size, int|void max_files) { FSGarb g = fsgarbs[id]; if (g) g->reconfigure(max_age, max_size, max_files); } } FSGarbWrapper register_fsgarb(string modid, string path, int max_age, int|void max_size, int|void max_files,
-
string|void quarantine)
+
string|void quarantine
,
+
int(0..1
)
|void cleanup_parent_dirs)
{ if ((path == "") || (path == "/") || (max_age <= 0)) return 0; string id = modid + "\0" + path + "\0" + gethrtime(); FSGarb g = FSGarb(modid, path, max_age, max_size, max_files,
-
quarantine);
+
quarantine
, cleanup_parent_dirs
);
fsgarbs[id] = g; GC_WERR("FSGC: Register garb on %O ==> id: %O\n", path, id); return FSGarbWrapper(id); } protected void start_fsgarb() { meta_fsgc_thread = Thread.Thread(meta_fsgc); Roxen.name_thread(meta_fsgc_thread, "Filesystem GC"); }