mldonkey-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Mldonkey-commits] mldonkey distrib/ChangeLog src/daemon/common/co...


From: mldonkey-commits
Subject: [Mldonkey-commits] mldonkey distrib/ChangeLog src/daemon/common/co...
Date: Tue, 24 Feb 2009 18:35:47 +0000

CVSROOT:        /sources/mldonkey
Module name:    mldonkey
Changes by:     spiralvoice <spiralvoice>       09/02/24 18:35:47

Modified files:
        distrib        : ChangeLog 
        src/daemon/common: commonBlocking.ml commonOptions.ml 
        src/daemon/driver: driverCommands.ml driverControlers.ml 
                           driverInterface.ml 
        src/networks/donkey: donkeyGlobals.ml donkeyOptions.ml 
        src/utils/net  : http_server.ml ip.ml ip.mli ip_set.ml 

Log message:
        patch #6752

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/mldonkey/distrib/ChangeLog?cvsroot=mldonkey&r1=1.1391&r2=1.1392
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/daemon/common/commonBlocking.ml?cvsroot=mldonkey&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/daemon/common/commonOptions.ml?cvsroot=mldonkey&r1=1.226&r2=1.227
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/daemon/driver/driverCommands.ml?cvsroot=mldonkey&r1=1.248&r2=1.249
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/daemon/driver/driverControlers.ml?cvsroot=mldonkey&r1=1.112&r2=1.113
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/daemon/driver/driverInterface.ml?cvsroot=mldonkey&r1=1.68&r2=1.69
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/networks/donkey/donkeyGlobals.ml?cvsroot=mldonkey&r1=1.121&r2=1.122
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/networks/donkey/donkeyOptions.ml?cvsroot=mldonkey&r1=1.67&r2=1.68
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/utils/net/http_server.ml?cvsroot=mldonkey&r1=1.38&r2=1.39
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/utils/net/ip.ml?cvsroot=mldonkey&r1=1.28&r2=1.29
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/utils/net/ip.mli?cvsroot=mldonkey&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/utils/net/ip_set.ml?cvsroot=mldonkey&r1=1.32&r2=1.33

Patches:
Index: distrib/ChangeLog
===================================================================
RCS file: /sources/mldonkey/mldonkey/distrib/ChangeLog,v
retrieving revision 1.1391
retrieving revision 1.1392
diff -u -b -r1.1391 -r1.1392
--- distrib/ChangeLog   24 Feb 2009 18:34:29 -0000      1.1391
+++ distrib/ChangeLog   24 Feb 2009 18:35:45 -0000      1.1392
@@ -15,6 +15,7 @@
 =========
 
 2009/02/24
+6752: Optimized implementation of the ip_set module (cbah)
 6736: Add/fix some copyright texts
 -------------------------------------------------------------------------------
 2009/01/20: version 2.9.7 = tag release-2-9-7

Index: src/daemon/common/commonBlocking.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonBlocking.ml,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- src/daemon/common/commonBlocking.ml 24 Jun 2007 18:38:28 -0000      1.8
+++ src/daemon/common/commonBlocking.ml 24 Feb 2009 18:35:46 -0000      1.9
@@ -37,7 +37,7 @@
 let country_blocking_string_list_copy = ref []
 
 let ip_set_hit bl ip =
-  match Ip_set.match_ip bl ip with
+  match Ip_set.match_blocking_range bl ip with
     | None -> None
     | Some br -> Some br.Ip_set.blocking_description
 

Index: src/daemon/common/commonOptions.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonOptions.ml,v
retrieving revision 1.226
retrieving revision 1.227
diff -u -b -r1.226 -r1.227
--- src/daemon/common/commonOptions.ml  20 Jan 2009 16:47:28 -0000      1.226
+++ src/daemon/common/commonOptions.ml  24 Feb 2009 18:35:46 -0000      1.227
@@ -452,7 +452,7 @@
   or 192.168.0.0-192.168.0.255 for 192.168.0.*"
     ip_range_list_option [ Ip.RangeSingleIp Ip.localhost ]
 
-let allowed_ips_set = ref Ip_set.BL_Empty
+let allowed_ips_set = ref Ip_set.bl_empty
 
 let _ =
   option_hook allowed_ips (fun _ ->

Index: src/daemon/driver/driverCommands.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverCommands.ml,v
retrieving revision 1.248
retrieving revision 1.249
diff -u -b -r1.248 -r1.249
--- src/daemon/driver/driverCommands.ml 31 Mar 2008 07:58:16 -0000      1.248
+++ src/daemon/driver/driverCommands.ml 24 Feb 2009 18:35:46 -0000      1.249
@@ -4108,9 +4108,8 @@
            ( "0", "srh ac br", "Description (" ^ tablename ^ ")", "Description 
(" ^ tablename ^ ")") ;
            ( "0", "srh ac br", "Hits", "Hits") ;
            ( "0", "srh ac", "Range", "Range")];
-          let nhits, nranges = 
-           Ip_set.bl_fold_left (fun br (nhits, nranges) ->
-             if br.Ip_set.blocking_hits > 0 then begin
+          let nhits = 
+           Ip_set.bl_fold_left (fun nhits br ->
                Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\"\\>"
                  (html_mods_cntr ());
                html_mods_td buf [
@@ -4120,9 +4119,9 @@
                    (Ip.to_string br.Ip_set.blocking_begin)
                    (Ip.to_string br.Ip_set.blocking_end))];
                Printf.bprintf buf "\\</tr\\>";
-             end;
-             (nhits + br.Ip_set.blocking_hits, nranges + 1)
-           ) (0, 0) l in
+             (nhits + br.Ip_set.blocking_hits)
+           ) 0 l 
+         and nranges = Ip_set.bl_length l in
          Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\"\\>"
            (html_mods_cntr ());
          if nranges > 0 then

Index: src/daemon/driver/driverControlers.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverControlers.ml,v
retrieving revision 1.112
retrieving revision 1.113
diff -u -b -r1.112 -r1.113
--- src/daemon/driver/driverControlers.ml       29 Jul 2008 12:30:09 -0000      
1.112
+++ src/daemon/driver/driverControlers.ml       24 Feb 2009 18:35:46 -0000      
1.113
@@ -585,7 +585,7 @@
             conn_info = Some (TELNET, (from_ip, from_port));
           } in
        (match Ip_set.match_ip !allowed_ips_set from_ip with
-       | Some br -> 
+       | true -> 
         TcpBufferedSocket.prevent_close sock;
         TcpBufferedSocket.set_max_output_buffer sock !!interface_buffer;
         TcpBufferedSocket.set_reader sock (user_reader o telnet);
@@ -604,7 +604,7 @@
 
         after_telnet_output o sock
 
-       | None ->
+       | false ->
         before_telnet_output o sock;
        let reject_message =
          Printf.sprintf "Telnet connection from %s rejected (see allowed_ips 
setting)\n"

Index: src/daemon/driver/driverInterface.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverInterface.ml,v
retrieving revision 1.68
retrieving revision 1.69
diff -u -b -r1.68 -r1.69
--- src/daemon/driver/driverInterface.ml        2 Jan 2008 16:50:16 -0000       
1.68
+++ src/daemon/driver/driverInterface.ml        24 Feb 2009 18:35:46 -0000      
1.69
@@ -1199,7 +1199,7 @@
       let from_ip = Ip.of_inet_addr from_ip in
       if not !verbose_no_login then lprintf_nl "GUI connection from %s" 
(Ip.to_string from_ip);
       (match Ip_set.match_ip !allowed_ips_set from_ip with
-      |        Some br ->
+      |        true ->
         
         let module P = GuiProto in
         let token = create_token unlimited_connection_manager in
@@ -1226,7 +1226,7 @@
             close sock Closed_for_overflow);
         (* sort GUIs in increasing order of their num *)
         
-      | None ->
+      | false ->
           if not !verbose_no_login then lprintf_nl "GUI connection from %s 
rejected (see allowed_ips setting)"
             (Ip.to_string from_ip);
           Unix.close s)
@@ -1238,7 +1238,7 @@
       let from_ip = Ip.of_inet_addr from_ip in
       lprintf "Gift: Connection from %s\n" (Ip.to_string from_ip);
       (match Ip_set.match_ip !allowed_ips_set from_ip with
-      | Some br ->
+      | true ->
         
         let module P = GuiProto in
         let token = create_token unlimited_connection_manager in
@@ -1264,7 +1264,7 @@
             close sock Closed_for_overflow);
         (* sort GUIs in increasing order of their num *)
         
-      | None ->
+      | false ->
           lprintf "Connection from IP %s not allowed\n"
             (Ip.to_string from_ip);
           Unix.close s)

Index: src/networks/donkey/donkeyGlobals.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyGlobals.ml,v
retrieving revision 1.121
retrieving revision 1.122
diff -u -b -r1.121 -r1.122
--- src/networks/donkey/donkeyGlobals.ml        3 Aug 2007 22:12:58 -0000       
1.121
+++ src/networks/donkey/donkeyGlobals.ml        24 Feb 2009 18:35:46 -0000      
1.122
@@ -485,9 +485,7 @@
   !!black_list && not (low_id ip) && (
 (* lprintf "is black ="; *)
     not (Ip.reachable ip) || 
-    (match Ip_set.match_ip !server_black_list_set ip with
-     | Some br -> true 
-     | None -> false) ||
+    (Ip_set.match_ip !server_black_list_set ip) || 
     (List.mem port !!port_black_list) ||
     (match !Ip.banned (ip, cc) with
         None -> false

Index: src/networks/donkey/donkeyOptions.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyOptions.ml,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -b -r1.67 -r1.68
--- src/networks/donkey/donkeyOptions.ml        31 Mar 2008 07:54:17 -0000      
1.67
+++ src/networks/donkey/donkeyOptions.ml        24 Feb 2009 18:35:46 -0000      
1.68
@@ -63,7 +63,7 @@
   Servers on this list can't be added, and will eventually be removed"
     CommonOptions.ip_range_list_option []
 
-let server_black_list_set = ref Ip_set.BL_Empty
+let server_black_list_set = ref Ip_set.bl_empty
 
 let () =
   option_hook server_black_list (fun _ ->

Index: src/utils/net/http_server.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/utils/net/http_server.ml,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -b -r1.38 -r1.39
--- src/utils/net/http_server.ml        26 May 2007 23:21:49 -0000      1.38
+++ src/utils/net/http_server.ml        24 Feb 2009 18:35:46 -0000      1.39
@@ -828,9 +828,7 @@
     (* check here if ip is OK *)
       let from_ip = Ip.of_inet_addr from_ip in
       let ip_is_allowed from_ip =
-       match Ip_set.match_ip config.addrs from_ip with
-       | Some br -> true
-       | None -> false
+       Ip_set.match_ip config.addrs from_ip
       in
       let ip_is_blocked from_ip =
        if config.use_ip_block_list then

Index: src/utils/net/ip.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/utils/net/ip.ml,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -b -r1.28 -r1.29
--- src/utils/net/ip.ml 26 May 2007 23:21:49 -0000      1.28
+++ src/utils/net/ip.ml 24 Feb 2009 18:35:47 -0000      1.29
@@ -36,6 +36,9 @@
   t.hi lsr 8, t.hi land 0xff,
   t.lo lsr 8, t.lo land 0xff
 
+let get_hi16 t = t.hi
+let get_lo16 t = t.lo
+
 external ints_of_string : string -> (int*int*int*int)  = "ml_ints_of_string"
 
 let of_string s =

Index: src/utils/net/ip.mli
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/utils/net/ip.mli,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- src/utils/net/ip.mli        26 May 2007 23:21:49 -0000      1.10
+++ src/utils/net/ip.mli        24 Feb 2009 18:35:47 -0000      1.11
@@ -21,6 +21,8 @@
 val of_inet_addr : Unix.inet_addr -> t
 val of_string : string -> t
 val of_ints : int * int * int * int -> t
+val get_lo16: t -> int
+val get_hi16: t -> int
 
 val to_inet_addr : t -> Unix.inet_addr
 val to_string : t -> string

Index: src/utils/net/ip_set.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/utils/net/ip_set.ml,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -b -r1.32 -r1.33
--- src/utils/net/ip_set.ml     1 Apr 2007 12:16:04 -0000       1.32
+++ src/utils/net/ip_set.ml     24 Feb 2009 18:35:47 -0000      1.33
@@ -1,6 +1,5 @@
 
 open Printf2
-open Ip
 open Gettext
 
 let _s x = _s "Ip_set" x
@@ -47,171 +46,339 @@
   blocking_description: string;
   blocking_begin: Ip.t;
   blocking_end: Ip.t;
-  mutable blocking_hits: int
+  blocking_hits: int
 }
 
+type short_entry = {
+    short_begin_high: int; (* 31..3 bits of IP address *)
+    sort_end_high: int; (* 31..3 bits of IP address *)    
+    mutable short_low_hits: int; (* 0..2 -> 0..2 bits of start address, 3..5 
-> 0..2 bits of end address, 6..30 -> 0..24 bits of counter *)
+    short_description: string;    
+  }
+
 let dummy_range = {
-  blocking_description = unknown_description;
-  blocking_begin = Ip.null;
-  blocking_end = Ip.null;
-  blocking_hits = 0 }
+  short_description = unknown_description;
+  short_begin_high = 0;
+  sort_end_high = 0;
+  short_low_hits = 0 }
 
 let store_blocking_descriptions = ref true
 
-(* Red-Black tree *)
+module Array2 = struct
+  type 'a t = {
+      mutable len: int;
+      mutable prev_len: int;
+      mutable a: 'a array
+    }
+  let length a = a.len
+  let set a n x = 
+    if n < a.len then a.a.(n) <- x
+    else invalid_arg "Array2.set"
+
+  let get a n = 
+    if n < a.len then a.a.(n) 
+    else invalid_arg "Array2.get"
+
+  let rec append a x = 
+    if a.len < Array.length a.a then begin
+      a.a.(a.len) <- x;
+      a.len <- a.len + 1;
+    end else begin
+      let new_len = a.len + a.prev_len 
+      and b = a.a.(0) in
+      (* lprintf_nl (_b "append resize[0] %d to %d") a.len new_len; *)
+
+      let t = Array.init new_len (fun n -> if n < a.len then a.a.(n) else b) in
+      a.prev_len <- a.len;
+      a.a <- t;
+      append a x;
+    end
+
+  let iter f a =
+    Array.iteri (fun n b -> if n < a.len then f b) a.a
+
+  let empty x = {len= 0 ; prev_len=1; a = Array.make 0 x}
+
+  let make n x = {len = n ; prev_len = n+1; a = Array.make (n+2) x} 
+
+  let init n f  = {len = n ; prev_len = n+1; a = Array.init n f}
+
+  let copy a = {len = a.len; prev_len = a.prev_len; a = Array.copy a.a}
+
+  let sort cmp a = 
+    if Array.length a.a != a.len then  a.a <- Array.init a.len (Array.get a.a);
+    Array.sort cmp a.a
+
+    
+
+end
+
+
+
+type compact = {
+    (* 
+       Instead of storing array of records, keep record of arrays. 
+       This way it eleminates need of boxing, so each entry occupies 3 words 
(if no description needed, the desc array isn't allocated).
+       Also on lookup only first array is accesed, unless hit is detected 
(better cache locality) and when hit detected, 
+       dara updated only in single array. 
+     *)
+    compact_begin_high: int array;
+    compact_end_high: int array; 
+    compact_low_hits: int array;
+    compact_desc: string array;
+  }
+
+(* either simple array or compact (non boxed) representation *)
 type blocking_list =
-    BL_Empty
-  | BL_Range of bool * blocking_list * blocking_range * blocking_list
+    Short of short_entry Array2.t
+  | Compact of compact
 
-let bl_empty = BL_Empty
 
-let ip_mini x y = if Ip.compare x y < 0 then x else y
+let bl_empty  = Short (Array2.make 0 dummy_range)
 
-let ip_maxi x y = if Ip.compare x y > 0 then x else y
+let bl_length bl = match bl with
+  Short  a -> Array2.length a
+| Compact  a -> Array.length a.compact_begin_high
 
-let rec add_range bl br =
-  blacken_root (ins bl br)
+let ip_split_hi ip =  (* msb 30 bits *)
+  ((Ip.get_hi16 ip) lsl 14) lor ((Ip.get_lo16 ip) lsr 2) 
 
-and ins bl br =
-  match bl with
-      BL_Empty -> BL_Range (true, BL_Empty, br, BL_Empty)
-    | BL_Range (red, left, br2, right) ->
-       if Ip.compare br.blocking_end br2.blocking_begin < 0 then
-         fixup (BL_Range (red, (ins left br), br2, right))
-       else if Ip.compare br.blocking_begin br2.blocking_end > 0 then
-         fixup (BL_Range (red, left, br2, (ins right br)))
-(* optimizer requires that ranges are sorted in increasing starting
-   addresses *)
-       else if Ip.compare br.blocking_begin br2.blocking_begin < 0 then 
-         fixup (BL_Range (red, (ins left br), br2, right))
+let ip_split_lo ip = (* lsb 2 bits *)
+  (Ip.get_lo16 ip) land 0x3 
+
+let ip_combine hi lo = 
+  Ip.of_ints ( (hi lsr 22), ((hi lsr 14) land 0xFF), ((hi lsr 6) land 0xFF), 
(((hi land 0x3F) lsl 2) lor lo))
+
+let init_low_bits begin_lo end_lo hits =
+  begin_lo lor (end_lo lsl 2) lor (hits lsl 4)
+
+let begin_low_bits n = 
+  n land 0x3
+
+let end_low_bits n = 
+  (n lsr 2) land 0x3 
+
+let get_hits n  =
+    n lsr 4
+  
+let succ_hits n = 
+  let count = (get_hits n) + 1 in
+  (n land 0xF) lor (count lsl 4)
+
+let make_br ip_begin ip_end desc = 
+  let begin_hi = ip_split_hi ip_begin
+  and begin_lo = ip_split_lo ip_begin
+  and end_hi = ip_split_hi ip_end
+  and end_lo = ip_split_lo ip_end in
+  {short_begin_high=begin_hi; 
+   sort_end_high=end_hi;
+   short_low_hits= init_low_bits begin_lo end_lo 0;
+   short_description=desc}
+
+
+let compare_split a_hi a_low b_hi b_low  = 
+  let hicompare = Pervasives.compare a_hi b_hi in
+  if hicompare <> 0 then 
+    hicompare
        else
-(* Be lazy. The optimizer will deal with it. *)
-         fixup (BL_Range (red, left, br2, (ins right br)))
-(*       let newr = {
-           blocking_description = br.blocking_description;
-           blocking_begin = ip_mini br.blocking_begin br2.blocking_begin;
-           blocking_end = ip_maxi br.blocking_end br2.blocking_end;
-           blocking_hits = br.blocking_hits + br2.blocking_hits } in
-         BL_Range (red, left, newr, right) *)
+    Pervasives.compare a_low b_low
 
-and fixup bl =
-  match bl with
-      BL_Range (false, a, x, BL_Range(true, b, y, BL_Range(true, c, z, d)))
-    | BL_Range (false, BL_Range(true, a, x, BL_Range(true, b, y, c)), z, d)
-    | BL_Range (false, BL_Range(true, BL_Range(true, a, x, b), y, c), z, d)
-    | BL_Range (false, a, x, BL_Range(true, BL_Range(true, b, y, c), z, d))
-      -> BL_Range(true, BL_Range(false, a, x, b), y, BL_Range(false, c, z, d))
-    | _ -> bl
+(* increment and then compare *)
+let compare_split_next a_hi a_low b_hi b_low  = 
+  if b_low < 3 then compare_split a_hi a_low b_hi (b_low + 1)
+  else compare_split a_hi a_low (b_hi+1) 0
 
-and blacken_root bl =
-  match bl with
-      BL_Empty -> BL_Empty
-    | BL_Range(_, left, v, right) -> BL_Range(false, left, v, right)
 
-let rec match_ip_aux bl ip =
+
+let match_ip_aux bl ip = 
+  let ip_hi = ip_split_hi ip 
+  and ip_lo = ip_split_lo ip in
   match bl with
-      BL_Empty -> None
-    | BL_Range (red, left, br, right) ->
-       if Ip.compare ip br.blocking_begin < 0 then
-         match_ip_aux left ip
-       else if Ip.compare ip br.blocking_end > 0 then
-         match_ip_aux right ip
-       else
-         Some br
+    Short a ->
+      let rec short_march_aux a ip_hi ip_lo n =
+       if n < Array2.length a then 
+         let br = Array2.get a n in
+         if (compare_split ip_hi ip_lo br.short_begin_high (begin_low_bits 
br.short_low_hits) >= 0) &
+           (compare_split ip_hi ip_lo br.sort_end_high (end_low_bits 
br.short_low_hits) <= 0) then begin
+             br.short_low_hits <- succ_hits br.short_low_hits;
+             n
+           end else short_march_aux a ip_hi ip_lo (n+1)
+       else -1 in
+      short_march_aux a ip_hi ip_lo 0
+  | Compact a ->      
+      let compare_begin a ip_hi ip_lo n =
+       let cmp_hi = Pervasives.compare ip_hi (Array.get a.compact_begin_high 
n) in
+       if cmp_hi <> 0 then cmp_hi
+       else Pervasives.compare ip_lo (begin_low_bits (Array.get 
a.compact_low_hits n))
+      and compare_end a ip_hi ip_lo n =
+       let cmp_hi = Pervasives.compare ip_hi (Array.get a.compact_end_high n) 
in
+       if cmp_hi <> 0 then cmp_hi
+       else Pervasives.compare ip_lo (end_low_bits (Array.get 
a.compact_low_hits n)) 
+      and mark_entry a n =
+       Array.set a.compact_low_hits n (succ_hits (Array.get a.compact_low_hits 
n));
+       n in
+
+      let rec binary_search_aux a ip_hi ip_lo lo hi =
+       if lo <= hi then 
+         let n = (lo + hi) / 2 in
+         let cmp = compare_begin a ip_hi ip_lo n in
+         if cmp < 0 then
+           binary_search_aux a ip_hi ip_lo lo (n-1)
+         else if cmp > 0 then
+           binary_search_aux a ip_hi ip_lo (n+1) hi
+         else mark_entry a n     
+       else begin
+         (* Printf.printf "%d %d\n" lo hi; *)
+         if hi >= 0 && hi < Array.length a.compact_begin_high then begin
+           let cmp = compare_begin a ip_hi ip_lo hi in
+           if cmp > 0 then
+             if (compare_end a ip_hi ip_lo hi) <= 0 then mark_entry a hi
+             else -1
+           else if cmp < 0 then -1
+           else mark_entry a hi
+         end else -1
+       end in
+      binary_search_aux a ip_hi ip_lo 0 ((Array.length a.compact_begin_high) - 
1)
+
+let make_range desc begin_high end_high low_hits = {
+   blocking_description = desc;
+   blocking_begin = ip_combine begin_high (begin_low_bits low_hits);
+   blocking_end = ip_combine end_high (end_low_bits low_hits);
+   blocking_hits = get_hits low_hits; } 
+
+let compact_get_desc a n = 
+  if Array.length a.compact_desc > n then Array.get a.compact_desc n else 
unknown_description
+
+let match_blocking_range bl ip =
+  let n = match_ip_aux bl ip in
+  if n >= 0 then Some (
+    match bl with
+      Short a -> 
+       let br = Array2.get a n in
+       make_range br.short_description br.short_begin_high br.sort_end_high 
br.short_low_hits
+    | Compact a ->
+       make_range (compact_get_desc a n) (Array.get a.compact_begin_high n) 
(Array.get a.compact_end_high n) (Array.get a.compact_low_hits n))
+  else None
+         
+       
+
+
 
 let match_ip bl ip =
-  let m = match_ip_aux bl ip in
-  (match m with
-      Some br ->
-       br.blocking_hits <- br.blocking_hits + 1
-    | None -> ());
-  m
+  match_ip_aux bl ip >= 0
+
+let append_range bl br =
+  match bl with
+    Short a ->
+      Array2.append a br
+  | Compact _ ->
+      assert(false)
 
-let rec bl_fold_left f acc bl =
+let copy_range bl = 
   match bl with
-      BL_Empty -> acc
-    | BL_Range (_, left, br, right) ->
-       bl_fold_left f (f br (bl_fold_left f acc left)) right
-
-let bl_optimize bl =
-  let compact br (new_bl, pending_br) =
-    match pending_br with
-(* first range *)
-       None -> (new_bl, Some br)
-      | Some pbr ->
-(* next range doesn't merge with pending one, commit pending range and
-   go on with the next one *)
-         if Ip.compare br.blocking_begin (Ip.succ pbr.blocking_end) > 0 then
-           (add_range new_bl pbr, Some br)
+    Short a ->
+      let b = Array2.copy a in
+      Short b
+  | Compact c ->
+      let b = Array2.init (Array.length c.compact_begin_high)
+         (fun n -> 
+           {
+            short_begin_high = Array.get c.compact_begin_high n;
+            sort_end_high = Array.get c.compact_end_high n;
+            short_low_hits = Array.get c.compact_low_hits n;
+            short_description = if Array.length c.compact_desc > n then 
Array.get c.compact_desc n  else unknown_description
+          }) in
+      Short b
+
+let add_range bl ip_begin ip_end desc =
+  let bl = copy_range bl 
+  and br = make_br ip_begin ip_end desc in
+  append_range bl br
+
+let br_compare r1 r2 = 
+  let cmp_begin = compare_split
+      r1.short_begin_high  (begin_low_bits r1.short_low_hits) 
+      r2.short_begin_high (begin_low_bits r2.short_low_hits) in
+  if cmp_begin <> 0 then 
+    cmp_begin
          else 
-           let hits_sum = br.blocking_hits + pbr.blocking_hits in
-(* next range merge with pending one, does it extend it ? *)
-           if Ip.compare br.blocking_end pbr.blocking_end > 0 then
-           (new_bl, Some { pbr with blocking_end = br.blocking_end;
-                           blocking_hits = hits_sum })
+    compare_split 
+      r1.sort_end_high  (end_low_bits r1.short_low_hits) 
+      r2.sort_end_high (end_low_bits  r2.short_low_hits)
+
+  let bl_optimize a = 
+  match a with
+    Short a ->     
+      (* lprintf_nl (_b "sort %d") (Array2.length a); *)
+      Array2.sort br_compare a;
+      let rec bl_optimize_aux a rd wr last_hi last_lo  =
+       if rd < Array2.length a then
+         let br = Array2.get a rd
+         and rd = rd + 1 in
+         if (compare_split br.sort_end_high (end_low_bits br.short_low_hits) 
last_hi last_lo) > 0 then begin (* new record is going further then last *)
+           if wr >= 0 && (compare_split_next br.short_begin_high 
(begin_low_bits br.short_low_hits) last_hi  last_lo) <= 0 then begin (* but it 
starts inside previous block, so concatenate them *)
+             let last_hi = br.sort_end_high
+             and last_lo = (end_low_bits br.short_low_hits) in
+             let prev = Array2.get a wr  in
+             Array2.set a wr {short_begin_high = prev.short_begin_high;
+                              sort_end_high = last_hi;
+                              short_low_hits = init_low_bits  (begin_low_bits 
prev.short_low_hits)  last_lo
+                                ((get_hits prev.short_low_hits) + (get_hits 
br.short_low_hits));
+                              short_description = prev.short_description};
+             bl_optimize_aux a rd wr last_hi last_lo
+           end else begin (* there is nothing to optimize *)
+             let wr = wr+1 in
+             Array2.set a wr br;
+             bl_optimize_aux a rd wr br.sort_end_high (end_low_bits 
br.short_low_hits)
+           end 
+         end else (* just ignore current record *)
+           bl_optimize_aux a rd wr last_hi last_lo
          else 
-(* no, it doesn't *)
-           (new_bl, Some { pbr with blocking_hits = hits_sum })
-  in
+         wr+1 in
+      let len = bl_optimize_aux a 0 (-1) 0 0 in        
+      (* lprintf_nl (_b "copy %d") (Array2.length a); *)
+      Compact {
+      compact_begin_high = Array.init len (fun n -> (Array2.get a 
n).short_begin_high);
+      compact_end_high = Array.init len (fun n -> (Array2.get a 
n).sort_end_high);
+      compact_low_hits  = Array.init len (fun n -> (Array2.get a 
n).short_low_hits);
+      compact_desc = 
+      if !store_blocking_descriptions then
+       Array.init len (fun n -> (Array2.get a n).short_description)
+      else Array.make 0 unknown_description      
+    }
+  | Compact _ -> a
+  
 
-(* start with no current range *)
-  let new_bl, pending_br = bl_fold_left compact (bl_empty, None) bl in
-(* finally, add the pending range *)
-  match pending_br with
-      None -> new_bl
-    | Some pbr -> add_range new_bl pbr
-
-let bl_length bl =
-  bl_fold_left (fun br acc -> acc+1) 0 bl
-
-let bl_optimizedp bl =
-  let last_ip = ref None in
-  let check br () =
-    (match !last_ip with
-       Some ip ->
-         assert(Ip.compare br.blocking_begin ip > 0)
-      | None -> ());
-    last_ip := Some (Ip.succ br.blocking_end)
-  in bl_fold_left check () bl
 
 let load_merge bl filename remove =
   let guardian_regexp = Str.regexp "^\\(.*\\): 
*\\([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\\)-\\([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\\)"
 in
   let ipfilter_regexp = Str.regexp "^\\([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\\) 
*- *\\([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\\) *, *[0-9]+ *, *\\(.*\\)$" in
 
-  let bl = ref bl in
+  let bl = copy_range bl in
   let nranges = ref 0 in
   let error = ref false in
   Unix2.tryopen_read filename (fun cin ->
   let nlines = ref 0 in
+  let append line ip_begin ip_end desc = 
+    let ip_begin = Ip.of_string (Str.matched_group ip_begin line) 
+    and ip_end = Ip.of_string (Str.matched_group ip_end line)
+    and desc = 
+      if !store_blocking_descriptions then 
+       shared_description (Str.matched_group desc line) 
+      else 
+       unknown_description in
+    append_range bl (make_br ip_begin ip_end desc);
+    incr nranges in  
   try
     while true do
       let line = input_line cin in
         incr nlines;
        try
-         if Str.string_match ipfilter_regexp line 0 then begin
-           let br = {
-             blocking_description = if !store_blocking_descriptions then 
-               shared_description (Str.matched_group 3 line) 
-             else 
-               unknown_description;
-             blocking_begin = Ip.of_string (Str.matched_group 1 line);
-             blocking_end = Ip.of_string (Str.matched_group 2 line);
-             blocking_hits = 0 } in
-           bl := add_range !bl br;
-           incr nranges
-         end else 
-           if Str.string_match guardian_regexp line 0 then begin
-             let br = {
-               blocking_description = if !store_blocking_descriptions then 
-                 shared_description (Str.matched_group 1 line) 
+         if Str.string_match ipfilter_regexp line 0 then
+           append line 1 2 3
+         else if Str.string_match guardian_regexp line 0 then 
+           append line 2 3 1
                else 
-                 unknown_description;
-               blocking_begin = Ip.of_string (Str.matched_group 2 line);
-               blocking_end = Ip.of_string (Str.matched_group 3 line);
-               blocking_hits = 0 } in
-             bl := add_range !bl br;
-             incr nranges
-           end else 
              raise Not_found
        with _ ->
          if not !error then
@@ -224,16 +391,8 @@
   with End_of_file -> ());
   if !error then lprint_newline ();
   if remove then (try Sys.remove filename with _ -> ());
-  let optimized_bl = bl_optimize !bl in
+  let optimized_bl = bl_optimize bl in
   lprintf_nl (_b "%d ranges loaded - optimized to %d") !nranges (bl_length 
optimized_bl);
-(*    bl_optimizedp optimized_bl;
-    for i=0 to 999999 do
-      let random_ip = Ip.of_ints (Random.int 256, Random.int 256, Random.int 
256, Random.int 256) in
-      match match_ip !bl random_ip, match_ip optimized_bl random_ip with
-         None, None 
-       | Some _, Some _ -> ()
-       | _ -> assert false
-    done; *)
   optimized_bl
 
 let load filename =
@@ -303,45 +462,56 @@
     end
 
 let of_list l =
-  bl_optimize (
-  List.fold_left (fun acc r ->
+  let bl = copy_range  bl_empty in
+  List.iter (fun r ->
     let range =
       match r with
-      | Ip.RangeSingleIp ip -> {
-         dummy_range with
-         blocking_begin = ip;
-         blocking_end = ip }
-      | Ip.RangeRange (ip1, ip2) -> {
-         dummy_range with
-         blocking_begin = ip1;
-         blocking_end = ip2 }
+      | Ip.RangeSingleIp ip -> 
+         make_br ip ip unknown_description
+      | Ip.RangeRange (ip1, ip2) -> 
+         make_br ip1 ip2 unknown_description
       | Ip.RangeCIDR (ip, shift) ->
        let mask = Ip.mask_of_shift shift in
-       { dummy_range with
-         blocking_begin = Ip.network_address ip mask;
-         blocking_end = Ip.broadcast_address ip mask }
+       make_br (Ip.network_address ip mask) (Ip.broadcast_address ip mask) 
unknown_description
     in 
-    add_range acc range
-  ) BL_Empty l)
+    append_range bl range
+  ) l;
+  bl_optimize bl
+
+let bl_fold_left f a bl = 
+  let a' = ref a in
+  let f desc begin_high end_high low_hits = 
+    a' := f !a' (make_range desc begin_high end_high low_hits) in
+
+  (match bl with
+    Short a ->   
+      Array2.iter (fun br ->   
+       if  get_hits br.short_low_hits > 0 then 
+         f br.short_description br.short_begin_high br.sort_end_high 
br.short_low_hits;
+                 ) a
+  | Compact a ->
+      Array.iteri (fun n low_hits ->
+       if  get_hits low_hits > 0 then
+         f (compact_get_desc a n)
+           (Array.get a.compact_begin_high n) (Array.get a.compact_end_high n) 
low_hits
+                 ) a.compact_low_hits);
+  !a'
+
 
 let print_list buf bl =
-  let rec print_list_aux bl =
-    match bl with
-        BL_Empty -> 0
-      | BL_Range (red, left, br, right) ->
-          let nleft = print_list_aux left in
-          if br.blocking_hits > 0 then
+  let print_entry () br = 
             Printf.bprintf buf "%s (%d hits): %s - %s\n" 
               br.blocking_description
               br.blocking_hits
               (Ip.to_string br.blocking_begin)
-              (Ip.to_string br.blocking_end);
-          let nright = print_list_aux right in
-          nleft + 1 + nright in
-
-  let nranges = print_list_aux bl in
+      (Ip.to_string br.blocking_end) in
+  bl_fold_left print_entry () bl;
+  let nranges = bl_length bl in
   Printf.bprintf buf "%d ranges\n" nranges
 
+
+      
+
 (*
 open Benchmark
 
@@ -368,3 +538,4 @@
       let counter = ref 0 in
       H.iter (fun _ -> incr counter) descriptions;
       Printf.bprintf buf "  descriptions: %d\n" !counter)
+




reply via email to

[Prev in Thread] Current Thread [Next in Thread]