From: Sapan Bhatia Date: Tue, 31 Jul 2007 19:59:05 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: vsys-0.7-19~28 X-Git-Url: http://git.onelab.eu/?p=vsys.git;a=commitdiff_plain;h=a9f606051125de2acc9140074f91054755fa67b4 *** empty log message *** --- diff --git a/.dep b/.dep index 63f8791..3ec5199 100644 --- a/.dep +++ b/.dep @@ -1,7 +1,3 @@ -backend.cmo: inotify.cmi globals.cmo frontend.cmo fifowatcher.cmo \ - dirwatcher.cmo -backend.cmx: inotify.cmi globals.cmx frontend.cmx fifowatcher.cmx \ - dirwatcher.cmx dirwatcher.cmo: inotify.cmi globals.cmo fdwatcher.cmo dirwatcher.cmx: inotify.cmi globals.cmx fdwatcher.cmx fdwatcher.cmo: globals.cmo diff --git a/Makefile b/Makefile index 96937bb..3bf56a6 100644 --- a/Makefile +++ b/Makefile @@ -23,10 +23,13 @@ include .dep .mll.ml: ocamllex $< -vsys: inotify.cmxa inotify.cmi globals.cmx fdwatcher.cmx dirwatcher.cmx fifowatcher.cmx frontend.cmx backend.cmx main.cmx +docs: *.ml + cd docs && ocamldoc -d . -html ../*.ml + +vsys: inotify.cmxa inotify.cmi globals.cmx fdwatcher.cmx dirwatcher.cmx fifowatcher.cmx frontend.cmx backend.cmx main.cmx docs ocamlopt str.cmxa unix.cmxa inotify.cmxa globals.cmx fdwatcher.cmx dirwatcher.cmx fifowatcher.cmx frontend.cmx backend.cmx str.cmxa main.cmx -o vsys -vsys.b: inotify.cma inotify.cmi globals.cmo fdwatcher.cmo dirwatcher.cmo fifowatcher.cmo frontend.cmo backend.cmo main.cmo +vsys.b: inotify.cma inotify.cmi globals.ml fdwatcher.ml dirwatcher.ml fifowatcher.ml frontend.ml backend.ml main.ml ocamlc -g str.cmxa unix.cma inotify.cma globals.cmo fdwatcher.cmo dirwatcher.cmo fifowatcher.cmo frontend.cmo backend.cmo str.cma main.cmo -o vsys.b install: vsys diff --git a/backend.ml b/backend.ml index 1cf44a4..7d00cfd 100644 --- a/backend.ml +++ b/backend.ml @@ -1,3 +1,12 @@ +(** backend.ml: + Defines handlers for events related to the backend directory, where the + scripts are stored. Eg. a new script results in a new part of pipes in + the frontend etc. These handlers are defined in the backendHandler + class. + + @author Sapan Bhatia + *) + open Unix open Globals open Dirwatcher @@ -6,14 +15,20 @@ open Fifowatcher open Frontend open Printf +(** Helper functions: + +*) + +(** Turn an absolute path into a relative path. *) let delete_prefix prefix str = let len = String.length str in let plen = String.length prefix in if (String.sub str 0 plen <> prefix) then + (* XXX can a user make this happen? *) raise Bad_path else - Relpath(String.sub str (plen+1) (len-plen-1)) + Relpath(String.sub str (plen+1) (len-plen-1)) let rec list_check lst elt = match lst with @@ -21,99 +36,144 @@ let rec list_check lst elt = | car::cdr -> if (car==elt) then true else list_check cdr elt - (* - * One backendHandler class for each - * backend. Builds the initial - * tree for the frontend and - * watches for directory - * events. - *) - +(** The backendhandler class: defines event handlers for events in +the backend backend directory. + @param dir_root The location of the backend in the server context (eg. root context for vservers) + @param frontend_list List of frontends to serve with this backend + *) class backendHandler dir_root (frontend_lst: frontendHandler list) = - let mk_rel_path = delete_prefix dir_root in object(this) + let mk_rel_path = delete_prefix dir_root in object(this) + + (** Regular expression that defines a legal script name. Filter out + * temporary files using this *) + val file_regexp = Str.regexp "[a-zA-Z][a-zA-Z0-9_\.]*" + val acl_file_regexp = Str.regexp ".*acl$" - val file_regexp = ref (Str.regexp "[a-zA-Z][a-zA-Z0-9_\.]*") + val dir_regexp = Str.regexp "^dir_"; + val acl_regexp = Str.regexp ".*_.*"; - method new_dir fqp func = - let s = Unix.stat fqp in - List.iter - (fun frontend-> - frontend#mkdir (mk_rel_path fqp) (s.st_perm); - Dirwatcher.add_watch fqp [S_Create;S_Delete] (Some(func))) - frontend_lst; + (** Somebody created a new directory *) + (* XXX Race condition here *) + method private new_dir slice_list fqp func = + let s = Unix.stat fqp in + List.iter + (fun frontend-> + frontend#mkdir (mk_rel_path fqp) (s.st_perm); + Dirwatcher.add_watch fqp [S_Create;S_Delete] (Some(func))) + slice_list - method new_script fqp = - let s = Unix.stat fqp in - List.iter (fun frontend-> - frontend#mkentry (mk_rel_path fqp) fqp (s.st_perm)) frontend_lst + (** Somebody copied in a new script *) + (* XXX Race condition here *) + method private new_script slice_list fqp = + let s = Unix.stat fqp in + List.iter (fun frontend-> + frontend#mkentry (mk_rel_path fqp) fqp (s.st_perm)) slice_list - val dir_regexp = Str.regexp "^dir_"; + method private make_filter acl_fqp = + let filter = Hashtbl.create 16 in + try + let acl_file = open_in acl_fqp in + let rec read_acl cur_filter = + let next_item = + try Some(input_line acl_file) + with _ -> None + in + match next_item with + | None -> cur_filter + | Some(item) -> + Hashtbl.add cur_filter item true; + read_acl cur_filter + in + Some(read_acl filter) + with _ -> + None - method handle_dir_event dirname evlist fname = - let fqp = String.concat "/" [dirname;fname] in - if (Str.string_match !file_regexp fname 0) then - begin - let is_event = list_check evlist in - if (is_event Create) then - begin - if (is_event Isdir) then - begin - this#new_dir fqp this#handle_dir_event - end - else - (* It's a new script *) - begin - (* - if (Str.string_match dir_regexp fname 0) then - let fqp = String.concat "/" [dirname;String.sub fname 4 ((String.length fname)-4+1)] in - let real_fqp = String.concat "/" [dirname;fname] in - this#new_dir fqp this#handle_spool_event; - Hashtbl.add spools fqp real_fqp - else*) - this#new_script fqp - end - end - else if (is_event Delete) then - begin - if (is_event Isdir) then - begin - (*this#rm_watch fqp;*) - List.iter (fun frontend-> - frontend#rmdir (mk_rel_path fqp)) frontend_lst - end - else List.iter (fun frontend -> - frontend#unlink (mk_rel_path fqp)) frontend_lst - end - end - else (* regex not matched *) - () + (** Gets called every time there's an inotify event at the backend + @param dirname Name of the backend directory + @param evlist Description of what happened + @param fname Name of the file that the event applies to + *) + method handle_dir_event dirname evlist fname = + let fqp = String.concat "/" [dirname;fname] in + if ((Str.string_match file_regexp fname 0) && not (Str.string_match acl_file_regexp fname 0)) then + begin + (* Filter frontend list based on acl *) + let acl_fqp = String.concat "." [fqp;"acl"] in + let acl_filter = this#make_filter acl_fqp in + let slice_list = + match acl_filter with + | None -> frontend_lst + | Some(filter) -> List.filter (fun fe->Hashtbl.mem filter (fe#get_slice_name ())) frontend_lst + in + let is_event = list_check evlist in + if (is_event Create) then + begin + if (is_event Isdir) then + begin + this#new_dir slice_list fqp this#handle_dir_event + end + else + (* It's a new script *) + begin + (* + if (Str.string_match dir_regexp fname 0) then + let fqp = String.concat "/" [dirname;String.sub fname 4 ((String.length fname)-4+1)] in + let real_fqp = String.concat "/" [dirname;fname] in + this#new_dir fqp this#handle_spool_event; + Hashtbl.add spools fqp real_fqp + else*) + this#new_script slice_list fqp + end + end + else if (is_event Delete) then + begin + if (is_event Isdir) then + begin + (*this#rm_watch fqp;*) + List.iter (fun frontend-> + frontend#rmdir (mk_rel_path fqp)) slice_list + end + else List.iter (fun frontend -> + frontend#unlink (mk_rel_path fqp)) slice_list + end + end + else (* regex not matched *) + () - initializer - let rec build_initial_tree dir = - let dir_handle = opendir dir in - let cont = ref true in - while (!cont) do - try - let curfile = readdir dir_handle in - let fqp = String.concat "/" [dir;curfile] in - if (Str.string_match !file_regexp curfile 0) then - let s = Unix.stat fqp in - begin - match s.st_kind with - | S_DIR -> - this#new_dir fqp this#handle_dir_event; - build_initial_tree fqp; - | S_REG -> - this#new_script fqp - | _ -> - printf "Don't know what to do with %s\n" curfile;flush Pervasives.stdout - end - with - _->cont:=false;() - done - in - begin - build_initial_tree dir_root; - Dirwatcher.add_watch dir_root [S_Create;S_Delete] (Some(this#handle_dir_event)); - end -end + (** Initializer - build the initial tree based on the contents of /vsys *) + initializer + let rec build_initial_tree dir = + let dir_handle = opendir dir in + let cont = ref true in + while (!cont) do + try + let curfile = readdir dir_handle in + let fqp = String.concat "/" [dir;curfile] in + let acl_fqp = String.concat "." [fqp;"acl"] in + let acl_filter = this#make_filter acl_fqp in + let slice_list = + match acl_filter with + | None -> frontend_lst + | Some(filter) -> List.filter (fun fe->Hashtbl.mem filter (fe#get_slice_name ())) frontend_lst + in + if (Str.string_match file_regexp curfile 0 && not (Str.string_match acl_file_regexp curfile 0)) then + let s = Unix.stat fqp in + begin + match s.st_kind with + | S_DIR -> + this#new_dir slice_list fqp this#handle_dir_event; + build_initial_tree fqp; + | S_REG -> + this#new_script slice_list fqp + | _ -> + printf "Don't know what to do with %s\n" curfile;flush Pervasives.stdout + end + with + _->cont:=false;() + done + in + begin + build_initial_tree dir_root; + Dirwatcher.add_watch dir_root [S_Create;S_Delete] (Some(this#handle_dir_event)); + end + end diff --git a/frontend.ml b/frontend.ml index 194d7ce..77e5ffe 100644 --- a/frontend.ml +++ b/frontend.ml @@ -5,6 +5,7 @@ open Fifowatcher class frontendHandler (root_dir,slice_name) = object(this) + method get_slice_name () = slice_name method mkentry (rp:relpath) abspath perm = let realperm = perm land (lnot 0o111) in match rp with Relpath(rel) -> diff --git a/globals.ml b/globals.ml index 26230b8..8b006c3 100644 --- a/globals.ml +++ b/globals.ml @@ -1,8 +1,10 @@ -let frontend = ref "" let backend = ref "" let debug = ref true +let vsys_version = "0.5" type fd_and_fname = string option * Unix.file_descr + +(* Relative path, never precededed by a '/' *) type relpath = Relpath of string exception Bad_path diff --git a/main.ml b/main.ml index 2d4057d..c42b1c2 100644 --- a/main.ml +++ b/main.ml @@ -18,7 +18,7 @@ let cmdspeclist = let cont = ref true let _ = - printf "Vsys v0.4\n";flush stdout; + printf "Vsys v%s\n" Globals.vsys_version;flush stdout; Arg.parse cmdspeclist (fun x->()) "Usage: vsys "; if (!Globals.backend == "" || !input_file_list == []) then printf "Try vsys --help\n" diff --git a/vsys b/vsys index 473050d..506806e 100755 Binary files a/vsys and b/vsys differ