1 (* Copyright (C) 2002, HELM Team.
3 * This file is part of HELM, an Hypertextual, Electronic
4 * Library of Mathematics, developed at the Computer Science
5 * Department, University of Bologna, Italy.
7 * HELM is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * HELM is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with HELM; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 * For details, see the HELM World-Wide-Web page,
23 * http://cs.unibo.it/helm/.
27 let debug_print s = if debug then prerr_endline s;;
28 Http_common.debug := debug;;
32 let daemon_name = "Uri Set Queue";;
33 let default_port = 48082;;
34 let port_env_var = "URI_SET_QUEUE_PORT";;
36 module OrderedUri: Set.OrderedType with type t = string =
41 module UriSet = Set.Make (OrderedUri)
44 mutable overflowed: bool;
46 mutable olduris: UriSet.t;
48 (** raised when a queue is accessed before being defined *)
49 exception Queue_not_found of int;;
50 (** global uri_queue, used by all children *)
52 size = 0; overflowed = false; uris = Queue.create (); olduris = UriSet.empty
54 let (get_queue, add_queue, remove_queue) =
55 let uri_queues = Hashtbl.create 17 in
56 ((fun pid -> (* get_queue *)
58 Hashtbl.find uri_queues pid
59 with Not_found -> raise (Queue_not_found pid)),
60 (fun pid size -> (* add_queue *)
64 { size = size; overflowed = false;
65 uris = Queue.create (); olduris = UriSet.empty }),
66 (fun pid -> (* remove_queue *)
68 Hashtbl.remove uri_queues pid
69 with Not_found -> raise (Queue_not_found pid)))
73 let queue_mem item queue = (* mem function over queues *)
75 Queue.iter (fun e -> if item = e then raise Found) queue;
82 int_of_string (Sys.getenv port_env_var)
84 | Not_found -> default_port
85 | Failure "int_of_string" ->
86 prerr_endline "Warning: invalid port, reverting to default";
89 let callback (req: Http_types.request) outchan =
91 let res = new Http_response.response () in
93 res#setContentType "text/xml";
97 let (uri, pid) = (req#param "uri", int_of_string (req#param "PID")) in
98 debug_print (sprintf "Adding uri '%s' to queue '%d'" uri pid);
99 let queue = get_queue pid in
101 if (Queue.length queue.uris) + (UriSet.cardinal queue.olduris) >=
104 begin (* overflow! *)
105 queue.overflowed <- true;
106 debug_print "Answer: not_added_because_already_too_many";
107 "not_added_because_already_too_many"
108 end else begin (* there's room for another uri *)
109 if (queue_mem uri queue.uris) || (UriSet.mem uri queue.olduris)
111 begin (* url already in *)
112 debug_print "Answer: already_in";
114 end else begin (* uri not in *)
115 Queue.add uri queue.uris;
116 debug_print "Answer: added";
121 res#setBody (sprintf "<?xml version=\"1.0\"?>\n<%s/>\n" result);
122 if debug then res#serialize stderr;
123 Http_daemon.respond_with res outchan
125 | "/is_overflowed" ->
126 let pid = int_of_string (req#param "PID") in
127 let queue = get_queue pid in
128 let result = string_of_bool (queue.overflowed) in
129 debug_print (sprintf "%d queue is_overflowed = %s" pid result);
130 res#setBody (sprintf "<?xml version=\"1.0\"?>\n<%s/>\n" result);
131 if debug then res#serialize stderr;
132 Http_daemon.respond_with res outchan
134 | "/set_uri_set_size" ->
136 (int_of_string (req#param "PID"), int_of_string (req#param "size"))
138 debug_print (sprintf "Setting size '%d' for queue '%d'" size pid);
140 let queue = get_queue pid in
142 with Queue_not_found p ->
145 res#setBody "<?xml version=\"1.0\"?>\n<done/>\n";
146 if debug then res#serialize stderr;
147 Http_daemon.respond_with res outchan
150 let pid = int_of_string (req#param "PID") in
151 debug_print (sprintf "Getting next uri from queue '%d'" pid);
152 let queue = get_queue pid in
153 let element = (* xml response's root element *)
155 let uri = Queue.take queue.uris in
156 queue.olduris <- UriSet.add uri queue.olduris;
158 "<%suri value=\"%s\"/>"
159 (if queue.overflowed then "marked_" else "")
161 with Queue.Empty -> "<empty/>"
163 res#setBody ("<?xml version=\"1.0\"?>\n" ^ element ^ "\n");
164 if debug then res#serialize stderr;
165 Http_daemon.respond_with res outchan
167 | "/reset_to_empty" ->
168 let pid = int_of_string (req#param "PID") in
170 debug_print (sprintf "Resetting queue '%d'" pid);
171 res#setBody "<?xml version=\"1.0\"?>\n<done/>\n";
172 if debug then res#serialize stderr;
173 Http_daemon.respond_with res outchan
176 debug_print ("Invalid request received");
177 Http_daemon.respond_error ~status:(`Client_error `Bad_request) outchan);
178 prerr_endline "Request done!\n"
180 | Http_types.Param_not_found attr_name ->
181 Http_daemon.respond_error
182 ~status:(`Client_error `Bad_request)
183 ~body:(sprintf "Parameter '%s' is missing" attr_name)
185 | Failure "int_of_string" -> (* error in converting some paramters *)
186 Http_daemon.respond_error ~status:(`Client_error `Bad_request) outchan
187 | Queue_not_found queue_name ->
188 Http_daemon.respond_error
189 ~status:(`Client_error `Bad_request)
190 ~body:(sprintf "Queue '%d' is not defined" queue_name)
194 printf "%s started and listening on port %d\n" daemon_name port;
196 Http_daemon.start' ~port ~mode:`Thread callback;
197 printf "%s is terminating, bye!\n" daemon_name