(**************************************************************************)
(*                                                                        *)
(*  Ocamlviz --- real-time profiling tools for Objective Caml             *)
(*  Copyright (C) by INRIA - CNRS - Universite Paris Sud                  *)
(*  Authors: Julien Robert                                                *)
(*           Guillaume Von Tokarski                                       *)
(*           Sylvain Conchon                                              *)
(*           Jean-Christophe Filliatre                                    *)
(*           Fabrice Le Fessant                                           *)
(*  GNU Library General Public License version 2                          *)
(*  See file LICENSE for details                                          *)
(*                                                                        *)
(**************************************************************************)

open Printf
open Unix
open Options

let hostname s = 
  try
    let h = gethostbyname s in h.h_addr_list.(0)
  with _ -> try
    (* may be the address was passed as an IP number *)
    inet_addr_of_string s
  with _ -> try
    let h = gethostbyname "localhost" in h.h_addr_list.(0)
  with _ ->
    failwith "Netgame.hostname"

let server =
  let machine = if !machine="" then gethostname() else !machine in
  try
    let sock = socket PF_INET SOCK_STREAM 0 in
    let sockaddr = ADDR_INET(hostname machine, !port) in
    connect sock sockaddr;
    sock
  with Unix.Unix_error _ -> 
    printf "connection: couldn't connect to the server %s:%d\n" machine !port;
    exit 1

let buffer_size = 65536
let str = String.create buffer_size
let index = ref 0 (* first free slot in buffer str *)
let clean_up = ref 0

let recv str buffer_size = 
  match Unix.select [server] [] [] (-1.0) with
    [s] , _ , _ -> 
(* Fabrice: notice that now, this function returns the total size available
  in the buffer, and not only how much has been read during the last [recv]. *)
      !index + Unix.recv s str !index (buffer_size - !index) []
    | _ -> Format.eprintf "db.recv: could not read from server@."; exit 1


let tmp_string = ref None

let shift_left s last n =
  if last < n then begin
      let len = n - last in
      String.blit s last str 0 len;
      index := len
    end else 
    index := 0
  
let rec parse_messages s pos last =
  if last - pos >= 4 then begin
      let len_msg, pos2 = Binary.get_int31 s pos in
(*      Printf.eprintf "size=%d\n%!" len_msg; *)
      if last - pos2 >= len_msg then begin
(*          Printf.eprintf "a\n%!"; *)
          let msg, pos = Bproto.decode_one s pos2 last in
(*          Printf.eprintf "b\n%!"; *)
          (try Db.interp msg with _ -> ());
(*          Printf.eprintf "c\n%!"; *)
          parse_messages s pos last
        end
      else
      if len_msg + 4 > buffer_size then begin
(* Fabrice: we are in the case where the message is bigger than the default 
buffer size, we need to allocate a new buffer temporarily. *)
          let str = String.create (4+len_msg) in
          let len = last - pos in
(*          Printf.eprintf "moving %d from %d to str [%d]\n%!" len pos (4+len_msg); *)
          String.blit s pos str 0 len;
          index := len;
          tmp_string := Some str        
      end else
        shift_left s pos last      
    end else 
    shift_left s pos last
  
let receive () =
  match !tmp_string with
    None ->
      let n = recv str buffer_size in
      parse_messages str 0 n
  | Some str ->
      let len = String.length str in
(*      Printf.eprintf "waiting for %d from %d\n%!" len !index; *)
      let n = recv str len in
(*      Printf.eprintf "found %d\n%!" n; *)
      if n = len then begin
          tmp_string := None;
          parse_messages str 0 n
        end

  (*
      
      
  let msgl, last = Bproto.decode str 0 n in
  assert (last <= n);
  if last < n then begin
    let len = n - last in
    String.blit str last str 0 len;
    index := len
  end else 
    index := 0;
  List.iter Db.interp msgl
*)
        
let read_data () =
  while true do
    receive ();
    let rec_window = Db.get_record_window () in
    if !clean_up = (int_of_float rec_window) mod 10 
    then 
      begin
        Db.clean_up ();
        clean_up := 0
      end
    else incr clean_up 
  done




(*
Local Variables: 
compile-command: "unset LANG; make -C .."
End: 
*)
