Le Tuesday 11 September 2007 07:50:47 David Baelde, vous avez écrit :
> A possible way to do it: add an instance variable containing the time
> of the last connection attempt. If an attempt fails, just update it.
> At every output round (method send), if there is no connection, and
> the previous attempt was long ago (say, 3 seconds) try to start the
> output. This will be less violent, also the connection in the middle
> of streaming might cause a little latency if the server doesn't
> respond quickly... that's probably reasonable as a first
> implementation.
Here is the patch I just commited..
Romain
--
mama say
son, you've got to stay home today
there's a hole in the roof
you've got to make it waterproof
Index: outputs/icecast2.ml
===================================================================
--- outputs/icecast2.ml (révision 4559)
+++ outputs/icecast2.ml (copie de travail)
@@ -32,7 +32,11 @@
let proto =
[ "start", Lang.bool_t, Some (Lang.bool true),
Some "Start output threads on operator initialization." ;
-
+ "restart", Lang.bool_t, Some (Lang.bool false),
+ Some "Restart output after a failure. By default, liquidsoap will stop if the
+ output failed. Wrong user or password are not afected by this option" ;
+ "restart_delay", Lang.int_t, Some (Lang.int 3),
+ Some "Delay, in decond, before attempting new connection, if restart is enabled." ;
"host", Lang.string_t, Some (Lang.string "localhost"), None ;
"port", Lang.int_t, Some (Lang.int 8000), None ;
"user", Lang.string_t, Some (Lang.string "source"), None ;
@@ -60,7 +64,8 @@
let s v = e Lang.to_string v in
let autostart = e Lang.to_bool "start" in
-
+ let restart = e Lang.to_bool "restart" in
+ let restart_delay = float_of_int (e Lang.to_int "restart_delay") in
let host = s "host" in
let port = e Lang.to_int "port" in
let user = s "user" in
@@ -78,6 +83,7 @@
as super
val mutable connection = None
+ val mutable last_attempt = -1.
initializer
if sync then
@@ -85,20 +91,29 @@
method send b =
match connection with
- | None -> assert false
+ | None -> if restart &&
+ (last_attempt = -1.
+ ||
+ ((Unix.time ()) -. last_attempt) > restart_delay)
+ then
+ begin
+ self#output_start ;
+ self#send b
+ end
+ else if not restart then
+ failwith "shout connection failed!"
| Some c ->
(* TODO think about some limitation of shout restarting *)
- begin try
- if sync then Shout.sync c ;
- Shout.send c b
- with
- | Shout.Socket ->
- self#log#f 3 "%s"
- ("Shout socket error: timeout, network failure, "^
- "server shutdown? Restarting the output...") ;
- stop_output <- true ;
- start_output <- true
- end
+ begin try
+ if sync then Shout.sync c ;
+ Shout.send c b
+ with
+ | Shout.Socket ->
+ self#log#f 3 "%s"
+ ("Shout socket error: timeout, network failure, "^
+ "server shutdown? Restarting the output...") ;
+ last_attempt <- Unix.time ()
+ end
method output_stop =
match connection with
@@ -142,24 +157,39 @@
Configure.version
(get_agent conn)) ;
- begin
- try
- open_shout conn ;
- with
- | No_connect ->
- failwith
- (Printf.sprintf
- "unable to connect to icecast server %s:%d!"
- host port)
- | Socket ->
- failwith "invalid user or password for icecast login!"
- | No_login ->
- failwith "icecast mount point already taken, or wrong password!"
- end ;
+ (* Final *)
+ try
+ begin
+ try
+ open_shout conn ;
+ with
+ | No_connect as e ->
+ self#log#f 3
+ "unable to connect to icecast server %s:%d!"
+ host port ;
+ raise e
+ | Socket as e ->
+ self#log#f 3 "invalid user or password for icecast login!" ;
+ raise e
+ | No_login as e ->
+ self#log#f 3 "icecast mount point already taken, or wrong password!" ;
+ raise e
+ end ;
+
+ self#log#f 3 "Connection setup was successful." ;
+ connection <- Some conn
+ with
+ | No_connect | No_login as e ->
+ if restart then
+ begin
+ self#log#f 3 "connection failed, restarting output in %d sec"
+ (int_of_float restart_delay);
+ self#output_stop ;
+ last_attempt <- Unix.time ()
+ end
+ else
+ raise e
- self#log#f 3 "Connection setup was successful." ;
- connection <- Some conn
-
method output_reset =
self#output_stop ;
self#output_start