2 Defines handlers for events related to the backend directory, where the
3 scripts are stored. Eg. a new script results in a new part of pipes in
4 the frontend etc. These handlers are defined in the backendHandler
7 @author Sapan Bhatia <sapanb\@cs.princeton.edu>
18 (** Turn an absolute path into a relative path. *)
19 let delete_prefix prefix str =
20 let len = String.length str in
21 let plen = String.length prefix in
22 if (String.sub str 0 plen <> prefix)
24 (* XXX can a user make this happen? *)
27 Relpath(String.sub str (plen+1) (len-plen-1))
29 let rec list_check lst elt =
32 | car::cdr -> if (car==elt) then true else list_check cdr elt
34 (** The backendhandler class: defines event handlers for events in
35 the backend backend directory.
36 @param dir_root The location of the backend in the server context (eg. root context for vservers)
37 @param frontend_list List of frontends to serve with this backend
39 class backendHandler dir_root (frontend_lst: frontendHandler list) =
40 let mk_rel_path = delete_prefix dir_root in object(this)
42 (** Regular expression that defines a legal script name. Filter out
43 * temporary files using it *)
44 val file_regexp = Str.regexp "^[a-zA-Z][a-zA-Z0-9_\.\-]*$"
45 val acl_file_regexp = Str.regexp ".*acl$"
47 (** Somebody created a new directory *)
48 method private new_dir slice_list fqp func =
49 let s = Unix.stat fqp in
53 frontend#mkdir (mk_rel_path fqp) (s.st_perm);
54 Dirwatcher.add_watch fqp [S_Create;S_Delete] func
57 logprint "Could not create %s. Looks like a slice shot itself in the foot\n" fqp;
61 (** Somebody copied in a new script *)
62 method private new_script slice_list fqp =
63 let s = Unix.stat fqp in
64 List.iter (fun frontend->
65 frontend#mkentry (mk_rel_path fqp) fqp (s.st_perm))
68 method private make_filter acl_fqp =
69 let filter = Hashtbl.create 16 in
71 let acl_file = open_in acl_fqp in
72 let rec read_acl cur_filter =
74 try Some(input_line acl_file)
78 | None -> close_in acl_file;cur_filter
80 Hashtbl.add cur_filter item true;
87 method is_acl fname = Str.string_match acl_file_regexp fname 0
89 (** Gets called every time there's an inotify event at the backend
90 @param dirname Name of the backend directory
91 @param evlist Description of what happened
92 @param fname Name of the file that the event applies to
94 method handle_dir_event _ dirname evlist fname =
95 let fqp = String.concat "/" [dirname;fname] in
96 if ((Str.string_match file_regexp fname 0) && not (Str.string_match acl_file_regexp fname 0)) then
98 (* Filter frontend list based on acl *)
99 let acl_fqp = String.concat "." [fqp;"acl"] in
100 let acl_filter = this#make_filter acl_fqp in
102 match acl_filter with
103 | None -> [] (* No ACL *)
104 | Some(filter) -> List.filter
105 (fun fe->Hashtbl.mem filter (fe#get_slice_name ()))
108 let is_event = list_check evlist in
109 if (is_event Create) then
111 if (is_event Isdir) then
113 this#new_dir slice_list fqp this#handle_dir_event
116 (* It's a new script *)
118 this#new_script slice_list fqp
121 else if (is_event Delete) then
123 if (is_event Isdir) then
125 (*this#rm_watch fqp;*)
126 List.iter (fun frontend->
127 frontend#rmdir (mk_rel_path fqp)) slice_list
129 else List.iter (fun frontend ->
130 frontend#unlink (mk_rel_path fqp)) slice_list
133 else (* regex not matched *)
134 fprintf logfd "Rejected weird entry %s\n" fname
136 (** Initializer - build the initial tree based on the contents of /vsys *)
138 let rec build_initial_tree dir =
139 let dir_handle = opendir dir in
140 let cont = ref true in
143 let curfile = readdir dir_handle in
144 if (not (this#is_acl curfile)) then
146 let fqp = String.concat "/" [dir;curfile] in
147 let acl_fqp = String.concat "." [fqp;"acl"] in
148 let acl_filter = this#make_filter acl_fqp in
150 match acl_filter with
151 | None -> [] (*frontend_lst -> No ACL => No Show *)
152 | Some(filter) -> List.filter
153 (fun fe->Hashtbl.mem filter (fe#get_slice_name ()))
156 if (Str.string_match file_regexp curfile 0) then
157 let s = Unix.stat fqp in
161 this#new_dir slice_list fqp this#handle_dir_event;
162 build_initial_tree fqp;
164 this#new_script slice_list fqp
166 logprint "Don't know what to do with %s\n" curfile
174 build_initial_tree dir_root;
175 Dirwatcher.add_watch dir_root [S_Create;S_Delete] (this#handle_dir_event);