X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=daemon%2Fdaemon.ml;h=078aa3ab129b965a1efa961ba072434d5eedca79;hb=1d0b030e3a62a905dce16d05e8816cb3da8c49eb;hp=5b9fc3b8c6b9bc278229b6d384f8d3972c89bd14;hpb=c8bff8ac923645d517183b130158d61f85540b33;p=whenjobs.git diff --git a/daemon/daemon.ml b/daemon/daemon.ml index 5b9fc3b..078aa3a 100644 --- a/daemon/daemon.ml +++ b/daemon/daemon.ml @@ -82,6 +82,8 @@ let rec init j d = ~proc_set_variables ~proc_get_job_names ~proc_test_variables + ~proc_ping_daemon + ~proc_whisper_variables (Rpc_server.Unix addr) Rpc.Tcp (* not TCP, this is the same as SOCK_STREAM *) Rpc.Socket @@ -97,7 +99,7 @@ let rec init j d = and proc_reload_file () = if !debug then Syslog.notice "remote call: reload_file"; - try reload_file (); `ok + try reload_files (); `ok with Failure err -> `error err and proc_set_variable (name, value) = @@ -143,6 +145,7 @@ and proc_exit_daemon () = | Some s -> Rpc_server.stop_server ~graceful:true s; server := None; + Gc.compact (); (* force the server handle to get cleaned up now *) `ok and proc_get_jobs () = @@ -256,9 +259,74 @@ and proc_test_variables vars = (* Return the names. *) Array.of_list jobnames -(* Reload the jobs file. *) -and reload_file () = - let file = sprintf "%s/jobs.cmo" !jobsdir in +and proc_ping_daemon () = `ok + +and proc_whisper_variables vars = + try + let vars = Array.map ( + fun { Whenproto_aux.sv_name = name; sv_value = value } -> + name, variable_of_rpc value + ) vars in + let vars = Array.to_list vars in + + if !debug then + Syslog.notice "remote call: whisper_variables (%s)" + (String.concat " " + (List.map ( + fun (name, value) -> + sprintf "%s=%s" name (string_of_variable value) + ) vars)); + + List.iter (fun (name, _) -> check_valid_variable_name name) vars; + + (* Update all the variables atomically. *) + let s = List.fold_left ( + fun s (name, value) -> Whenstate.set_variable s name value + ) !state vars in + state := s; + + (* .. but don't reevaluate or run jobs. *) + + `ok + with + Failure msg -> `error msg + +(* Reload the jobs file(s). *) +and reload_files () = + (* Get the highest numbered dir/jobs__*.cmo (bytecode) or + * dir/jobs__*.cmxs (native code) file and load it. Delete + * lower-numbered (== older) files. + *) + let filename = + let suffix, slen = + if not Dynlink.is_native then ".cmo", 4 else ".cmxs", 5 in + let dir = !jobsdir in + let files = Array.to_list (Sys.readdir dir) in + let times = filter_map ( + fun file -> + if not (string_startswith file "jobs__") || + not (string_endswith file suffix) then + None + else ( + let len = String.length file in + let t = String.sub file 6 (len-slen-6) in + (* Use int64 because t won't necessarily fit into 31 bit int. *) + try Some (Int64.of_string t) + with Failure "int_of_string" -> assert false + ) + ) files in + let times = List.rev (List.sort compare times) in + match times with + | [] -> None + | x::xs -> + (* Unlink the older files. *) + List.iter ( + fun t -> + try unlink (dir // sprintf "jobs__%Ld%s" t suffix) + with Unix_error _ -> () + ) xs; + (* Return the newest (highest numbered) file. *) + Some (dir // sprintf "jobs__%Ld%s" x suffix) in (* As we are reloading the file, we want to create a new state * that has no jobs, but has all the variables from the previous @@ -268,18 +336,24 @@ and reload_file () = Whenfile.init s; let s = - try - Dynlink.loadfile file; - let s = Whenfile.get_state () in - Syslog.notice "loaded %d job(s) from %s" (Whenstate.nr_jobs s) file; + match filename with + | None -> + (* no jobs file, return the same state *) + Syslog.notice "no jobs file found"; s - with - | Dynlink.Error err -> - let err = Dynlink.error_message err in - Syslog.error "error loading jobs: %s" err; - failwith err - | exn -> - failwith (Printexc.to_string exn) in + | Some filename -> + try + Dynlink.loadfile filename; + let s = Whenfile.get_state () in + Syslog.notice "loaded %d job(s)" (Whenstate.nr_jobs s); + s + with + | Dynlink.Error err -> + let err = Dynlink.error_message err in + Syslog.error "error loading jobs: %s" err; + failwith err + | exn -> + failwith (Printexc.to_string exn) in let s = Whenstate.copy_prev_state !state s in state := s;