[divide-and-conquer~concur-next:4] State of play as of Dec. 9th.

  • From: TimBray@kenai.com
  • To: commits@divide-and-conquer.kenai.com
  • Subject: [divide-and-conquer~concur-next:4] State of play as of Dec. 9th.
  • Date: Thu, 10 Dec 2009 01:02:27 +0000

Project:    divide-and-conquer
Repository: concur-next
Revision:   4
Author:     TimBray
Date:       2009-12-10 01:02:25 UTC
Link:       

Log Message:
------------
State of play as of Dec. 9th.


Revisions:
----------
4


Modified Paths:
---------------
src/org/tbray/paralines.clj
src/org/tbray/overhead.clj
src/org/tbray/JOverhead.java
src/org/tbray/popular.clj
src/org/tbray/ref_based.clj
src/org/tbray/pop_agent.clj


Added Paths:
------------
src/org/tbray/read_lines.clj
src/org/tbray/wf2.clj


Diffs:
------
Index: src/org/tbray/ref_based.clj
===================================================================
--- src/org/tbray/ref_based.clj (revision 3)
+++ src/org/tbray/ref_based.clj (revision 4)
@@ -1,4 +1,3 @@
-
 (ns org.tbray.ref-based
   ;(:require )
   ;(:use )
Index: src/org/tbray/pop_agent.clj
===================================================================
--- src/org/tbray/pop_agent.clj (revision 3)
+++ src/org/tbray/pop_agent.clj (revision 4)
@@ -1,7 +1,5 @@
+(ns org.tbray.pop-agent)
 
-(ns org.tbray.pop-agent
-  )
-
 (def re #"GET /ongoing/When/\d\d\dx/(\d\d\d\d/\d\d/\d\d/[^ .]+) ")
 
 (defn add [so-far target]
Index: src/org/tbray/overhead.clj
===================================================================
--- src/org/tbray/overhead.clj  (revision 3)
+++ src/org/tbray/overhead.clj  (revision 4)
@@ -5,24 +5,22 @@
 
 (def READ-ONLY-MODE (. java.nio.channels.FileChannel$MapMode READ_ONLY))
 
-(defn blok [ channel offset size ]
-  (let [buffer (. channel map READ-ONLY-MODE offset size)
-        decoder (. (. java.nio.charset.Charset forName "UTF-8") newDecoder)
-        chars (. decoder decode buffer)
-        text (. chars toString)
-        tail (. text substring (- (. text length) 5))]
+(defn blok [ in size ]
+  (let [buffer (make-array Byte/TYPE size)
+        bytes (. in read buffer)]
     (println (str "T=" tail))))
 
 (defn blox [file-name settings]
   (let [block-size (or (settings :block-size) (* 32 1024 1024))
-        channel (. (new FileInputStream file-name) getChannel)
-        data-size (. channel size)
+        file (. new File file-name)
+        in (new FileInputStream file-name)
+        data-size (. file length)
         block-count (quot data-size block-size)
         tail-size (mod data-size block-size) ]
     (loop [index 0]
       (if (< index block-count)
         (do
-          (blok channel (* index block-size) block-size)
+          (blok in block-size)
           (recur (inc index)))))
-    (blok channel (* block-count block-size) tail-size)
+    (blok in tail-size)
     (println (str "DONE: " block-count " blocks."))))
Index: src/org/tbray/paralines.clj
===================================================================
--- src/org/tbray/paralines.clj (revision 3)
+++ src/org/tbray/paralines.clj (revision 4)
@@ -1,42 +1,52 @@
-
 (ns org.tbray.paralines
   (:import (java.io FileInputStream)))
 
 (def READ-ONLY-MODE (. java.nio.channels.FileChannel$MapMode READ_ONLY))
 
-(defn patcher 
-  "fragments is a map whose keys are of the form (str index :front|:back) 
telling you
-it's a partial line off the front or back of the block."
+(defn frag
+  "fragments is a map whose keys are of the form (str index :front|:back)"
   [fragments fragment index front-back]
-  (assoc fragments (str index front-back) (new String fragment)))
+  (dosync
+    (ref-set fragments (assoc @fragments (str index front-back) (new String 
fragment)))))
+
+(defn join-fragments [fragments-in params]
+  (loop [fragments fragments-in accum nil]
+    (if (not (empty? fragments))
+      (let [[key frag] (first fragments)
+            [istring fb] (. #":" split key)
+            index (new Integer istring)
+            is-front (= fb "front")
+            other-key (if is-front (str (dec index) ":back") (str (inc 
index) ":front"))
+            other (fragments other-key)
+            line (if is-front (str other frag) (str frag other))
+            next-accum ((params :per-line) accum line) ]
+        (recur (dissoc fragments key other-key) next-accum))
+      ((params :done-lines) accum))))
  
 (defn read-block
   "Read a block at the given index from the I/O channel, divide it up into
 lines and send them off to the destination. Also handle partials lines from 
the
 beginning and ends of blocks."
   [ b accumulator ] ; b short for block since we're using it a lot
-  (println (str "Block " (b :index)))
+  (if (= 0 (mod (b :index) 1000))
+    (println (str "Block " (b :index))))
   (let [buffer (. (b :channel) map READ-ONLY-MODE (b :offset) (b :size))
         decoder (. (. java.nio.charset.Charset forName "UTF-8") newDecoder)
-        chars (. decoder decode buffer)
-        text (. chars toString)
-        first-nl (. text indexOf 10)
-        front (. text substring 0 first-nl)
-        last-nl (. text lastIndexOf 10)
-        back (. text substring (inc last-nl))
-        fragments (b :fragments) index (b :index) per-line (b :per-line)]
+        text (. (. decoder decode buffer) toString)
+        index (b :index)
+        trailing-nl (. text endsWith "\n")
+        chunks (. #"\n" split text)
+        front (first chunks)
+        lc (get chunks (dec (count chunks))) ; (last chunks) tickles a 
Clojure 1.0 bug
+        back (if trailing-nl "" lc)
+        lines (if trailing-nl (rest chunks) (butlast (rest chunks)))
+        accum (reduce (b :per-line) accumulator lines) ] ; all the work 
happens here
 
-    (send fragments patcher front index :front)
-    (if (not (b :last))
-      (send fragments patcher back index :back))
-    (await fragments)
+    (frag (b :fragments) front index :front) ; save front/back fragments
+    (if (not last)
+      (frag (b :fragments) back index :back))
+    accum))
 
-    (loop [ nl first-nl accum accumulator ]
-      (let [ from (inc nl) to (. text indexOf 10 from) ]
-        (if (< from last-nl)
-          (recur to (per-line (new String (. text substring from to)) accum))
-          accum)))))
-
 (defn next-block [params index]
   (let [next (dosync (alter index inc))
         this (dec next)
@@ -51,7 +61,7 @@
   (loop [ accumulator nil block (next-block params index) ]
     (if block
       (recur (read-block block accumulator) (next-block params index))
-      ((params :per-line) nil accumulator))))
+      ((params :done-lines) accumulator))))
 
 ; There's probably a map/doseq/dorun one-liner that'll do this, sigh
 (defn make-threads [count params index]
@@ -70,9 +80,9 @@
             other-key (if is-front (str (dec index) ":back") (str (inc 
index) ":front"))
             other (fragments other-key)
             line (if is-front (str other frag) (str frag other))
-            next-accum ((params :per-line) line accum) ]
+            next-accum ((params :per-line) accum line)]
         (recur (dissoc fragments key other-key) next-accum))
-      ((params :per-line) nil accum))))
+      ((params :done-lines) accum))))
 
 (defn read-lines
   "Reads the named file and feeds the lines one at a time to the function
@@ -84,9 +94,9 @@
 value for the first (line) argument, that signals the final call in some 
given
 thread, so that the function may choose to do wind-up and reporting work.
 
-When all the lines have been processed, the the 'all-done' function will be 
+When all the lines have been processed, the the 'all-done' function will be
 called with 'user-data' as its single argument.  The 'destination' function
-will be called on multiple threads in parallel, so its logic must be 
+will be called on multiple threads in parallel, so its logic must be
 thread-safe.  There is no guarantee in which order the lines from the file
 will be processed.  The 'settings' argument is a map; the default values for 
the
 number of threads and file block-size may be overridden with the :width and
@@ -95,21 +105,19 @@
   (let [block-size (or (settings :block-size) (* 10 1024 1024))
         channel (. (new FileInputStream file-name) getChannel)
         data-size (. channel size)
-        fragments (agent {})
+        fragments (ref {})
         block-count (quot data-size block-size)
         thread-count (max 1 (min block-count (or (settings :width) 10)))
         tail-size (mod data-size block-size)
-        params {:block-count block-count
-                :block-size block-size
-                :tail-size tail-size
+        index (ref 0)
+        params {:block-count block-count :block-size block-size :tail-size 
tail-size
                 :channel channel
-                :per-line (fn [line accum] (destination line user-data 
accum))
+                :per-line (fn [accum #^String line] (destination (new String 
line) user-data accum))
+                :done-lines (fn [accum] (destination nil user-data accum))
                 :fragments fragments }
-        index (ref 0)
         threads (make-threads thread-count params index)]
 
-    ;; prime the first/last fragments pump
-    (send fragments patcher "" -1 :back)
+    (frag fragments "" -1 :back)  ; prime the fragments pump
 
     (doseq [thread threads]
       (.start thread)
@@ -117,6 +125,5 @@
 
     (doseq [thread threads]
       (.join thread))
-    (await fragments)
-    (join-fragments @fragments params)
+    (join-fragments (deref fragments) params)
     (all-done user-data)))
\ No newline at end of file
Index: src/org/tbray/wf2.clj
===================================================================
--- src/org/tbray/wf2.clj       (revision 0)
+++ src/org/tbray/wf2.clj       (revision 4)
@@ -0,0 +1,180 @@
+(ns org.tbray.wf2 
+ ;(:use clojure.contrib.test-is) ; having trouble getting this working on 
the production machine
+ )
+
+(def re #"^/ongoing/When/\d\d\dx/\d\d\d\d/\d\d/\d\d/[^ .]+$")
+(defn new-accum []  { :hits {} :bytes {} :404s {} :fetchers {} :referers {} 
})
+
+(defn bump [accum key uri increment]
+  (let [totals (accum key)
+        currently (if-let [total (totals uri)] total 0)]
+    (assoc accum key (assoc totals uri (+ currently increment)))))
+
+(defn merger [current incoming]
+  (loop [keys (keys current) output {}]
+    (if-let [key (first keys)]
+      (let [merge-1 (merge-with + (current key) (incoming key))]
+        (recur (rest keys) (assoc output key merge-1)))
+      output)))
+
+(defn proc-line [line so-far accum-1]
+  (if (nil? line)
+    (send so-far merger accum-1)
+    (let [accum-2 (if accum-1 accum-1 (new-accum))
+          fields (. #" " split line)
+          ; [client _ _ _ _ _ uri _ bstring status ref] (. #" " split line)
+          #^String uri-1 (aget fields 6) #^String uri (. uri-1 intern)
+          #^String status (aget fields 8)
+          accum-3 (if (= status "404") (bump accum-2 :404s uri 1) accum-2)
+          #^String bstring (aget fields 9)
+          accum-4 (if (re-find #"^\d+$" bstring)
+                    (bump accum-3 :bytes uri (new Integer bstring))
+                    accum-3)]
+      (if (re-find re uri)
+        (let [accum-5 (bump accum-4 :hits uri 1)
+              #^String ref (aget fields 10)
+              accum-6 (if (or (= ref "\"-\"") (re-find #"tbray.org/" ref))
+                        accum-5 (bump accum-5 :referers ref 1))
+              #^String client (aget fields 0)
+              accum-7 (bump accum-6 :fetchers client 1) ]
+          accum-7)
+        accum-4))))
+
+(defn top-10 [ hash ]
+  (take 10 (sort-by last (fn [a b] (> a b)) hash)))
+
+(defn print-report [stats-in]
+  (loop [stats stats-in]
+    (when-let [stat (first stats)]
+      (println (str "Top " (first stat)))
+      (println (str " ..." (first (last stat)) "... "))
+      (recur (rest stats)))))
+
+(defn report-wf2 [accum-ref]
+  (loop [accum @accum-ref stats {}]
+    (if-let [stat (first accum)]
+      (recur (rest accum) (assoc stats (first stat) (top-10 (last stat))))
+      (print-report stats))))
+
+(comment
+  (declare test-data)
+
+  (deftest test-wf2  ;; it's a smoke test not a unit test
+    (let [so-far (agent {})
+          per-line (fn [accum line] (proc-line line so-far accum))
+          accum-1 (reduce per-line nil test-data)
+          accum-2 (proc-line nil so-far accum-1)
+          stats (report-wf2 so-far)
+          ]
+      (do
+        (is (= (stats :404s) '(["/ongoing/serif.css" 2] 
["/ongoing/When/200x/2004/04/27/-/W3C/DTD%20XHTML%201.1/EN" 1])))
+        (is (= (stats :bytes) '(["/ongoing/ongoing.atom" 627776] 
["/ongoing/door60.jpg" 548800] ["/ongoing/When/200x/2003/05/06/Rune.png" 
293768] ["/ongoing/When/200x/2003/05/06/Glacier.png" 228856] 
["/ongoing/When/200x/2003/12/07/JVaughan.png" 189428] 
["/ongoing/When/200x/2007/03/29/IMG_0059.png" 169356] 
["/ongoing/When/200x/2005/08/05/IMG_3937.png" 152739] 
["/ongoing/When/200x/2007/06/15/IMGP5832.png" 131839] ["/ongoing/potd.png" 
80265] ["/ongoing/sans.css" 28932])))
+        (is (= (stats :hits) '(["/ongoing/When/200x/2007/06/17/Fathers-Day" 
3] ["/ongoing/When/200x/2003/10/16/Debbie" 1] 
["/ongoing/When/200x/2003/09/03/McLaren" 1] 
["/ongoing/When/200x/2007/03/29/Maxed" 1] 
["/ongoing/When/200x/2004/04/27/RSSticker" 1] 
["/ongoing/When/200x/2003/05/06/2000Pix" 1] 
["/ongoing/When/200x/2006/08/25/Startup-Camp" 1] 
["/ongoing/When/200x/2007/06/15/Cameras" 1])))
+        (is (= (stats :fetchers) '(["proxy.ricoh.co.jp" 2] 
["cpc2-swan1-0-0-cust781.swan.cable.ntl.com" 1] 
["201-34-233-57.bsace704.dsl.brasiltelecom.net.br" 1] 
["pool-71-175-67-187.phlapa.fios.verizon.net" 1] 
["ras75-3-82-225-164-105.fbx.proxad.net" 1] 
["82-208-115-51.cs3-ats34-dzer.dialup.mts-nn.ru" 1] 
["adsl-074-229-029-232.sip.mia.bellsouth.net" 1] ["host-0014.tailrank.com" 1] 
["lj910366.inktomisearch.com" 1])))
+        (is (= (stats :referers) 
'(["\"http://cx1.src.ricoh.co.jp/wordpress/archives/213\"" 2] ;
["\"http://search.virginmedia.com/results/index.php?channel=other&q=debbie+does&cr=\"";
 1] ["\"http://www.tbray.org/ongoing/\"" 1] ["\"http://blogs.sun.com/\"" 1] ;
["\"http://images.google.com/imgres?imgurl=http://www.tbray.org/ongoing/When/200x/2003/05/06/-big/Glacier.jpg&imgrefurl=http://www.tbray.org/ongoing/When/200x/2003/05/06/2000Pix&h=642&w=960&sz=298&hl=en&start=31&um=1&tbnid=vrql887CTfKbeM:&tbnh=99&tbnw=148&prev=/images%3Fq%3Dglacier%2Bbay%26start%3D20%26ndsp%3D20%26svnum%3D10%26um%3D1%26hl%3Den%26client%3Dfirefox-a%26rls%3Dorg.mozilla:en-US:official%26sa%3DN\"";
 1])))
+        )))
+
+  (def test-data
+    ["gmp-ea-fw-1.sun.com - - [17/Jun/2007:22:45:55 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"Mozilla/5.0 (X11; U; SunOS 
sun4v; en-US; rv:1.8.0.5) Gecko/20060731 Firefox/1.5.0.5\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:45:56 -0700] \"GET 
/ongoing/When/200x/2007/06/15/Cameras HTTP/1.0\" 200 8152 
\"http://cx1.src.ricoh.co.jp/wordpress/archives/213\" \"Mozilla/4.0 ;
(compatible; MSIE 6.0; Windows NT 5.1; SV1)\""
+     "lj910366.inktomisearch.com - - [17/Jun/2007:22:45:57 -0700] \"GET 
/ongoing/When/200x/2006/08/25/Startup-Camp HTTP/1.0\" 200 5021 \"-\" 
\"Mozilla/5.0 (compatible; Yahoo! Slurp China; 
http://misc.yahoo.com.cn/help.html)\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:45:57 -0700] \"GET 
/ongoing/ongoing.js HTTP/1.0\" 200 6688 
\"http://www.tbray.org/ongoing/When/200x/2007/06/15/Cameras\" \"Mozilla/4.0 ;
(compatible; MSIE 6.0; Windows NT 5.1; SV1)\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:45:57 -0700] \"GET 
/ongoing/sans.css HTTP/1.0\" 200 4822 
\"http://www.tbray.org/ongoing/When/200x/2007/06/15/Cameras\" \"Mozilla/4.0 ;
(compatible; MSIE 6.0; Windows NT 5.1; SV1)\""
+     "host-0014.tailrank.com - - [17/Jun/2007:22:45:58 -0700] \"GET 
/ongoing/When/200x/2007/06/17/Fathers-Day HTTP/1.1\" 200 8251 \"-\" 
\"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1; aggregator:Tailrank; 
http://tailrank.com/robot) Gecko/20021130\""
+     "relay1.ops.re4.yahoo.net - - [17/Jun/2007:22:45:58 -0700] \"GET 
/ongoing/ongoing.rss HTTP/1.0\" 301 315 \"-\" \"Yahoo Pipes 1.0\""
+     "relay1.ops.re4.yahoo.net - - [17/Jun/2007:22:45:58 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.0\" 304 - \"-\" \"Yahoo Pipes 1.0\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:45:58 -0700] \"GET 
/ongoing/serif.css HTTP/1.0\" 200 4808 
\"http://www.tbray.org/ongoing/When/200x/2007/06/15/Cameras\" \"Mozilla/4.0 ;
(compatible; MSIE 6.0; Windows NT 5.1; SV1)\""
+     "207.241.145.68 - - [17/Jun/2007:22:45:58 -0700] \"GET 
/ongoing/ongoing.rss HTTP/1.1\" 301 322 \"-\" \"blogrunner-reaper 
(+http://www.blogrunner.com/)\""
+     "201-34-233-57.bsace704.dsl.brasiltelecom.net.br - - 
[17/Jun/2007:22:45:58 -0700] \"GET /ongoing/What/Arts/Movies/ HTTP/1.1\" 200 
12847 \"-\" \"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:45:59 -0700] \"GET 
/ongoing/Feed.png HTTP/1.0\" 200 786 
\"http://www.tbray.org/ongoing/When/200x/2007/06/15/Cameras\" \"Mozilla/4.0 ;
(compatible; MSIE 6.0; Windows NT 5.1; SV1)\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:45:59 
-0700] \"GET /ongoing/When/200x/2003/05/06/2000Pix HTTP/1.1\" 200 6302 
\"http://images.google.com/imgres?imgurl=http://www.tbray.org/ongoing/When/200x/2003/05/06/-big/Glacier.jpg&imgrefurl=http://www.tbray.org/ongoing/When/200x/2003/05/06/2000Pix&h=642&w=960&sz=298&hl=en&start=31&um=1&tbnid=vrql887CTfKbeM:&tbnh=99&tbnw=148&prev=/images%3Fq%3Dglacier%2Bbay%26start%3D20%26ndsp%3D20%26svnum%3D10%26um%3D1%26hl%3Den%26client%3Dfirefox-a%26rls%3Dorg.mozilla:en-US:official%26sa%3DN\";
 \"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) 
Gecko/20070508 Firefox/1.5.0.12\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:45:59 
-0700] \"GET /ongoing/sans.css HTTP/1.1\" 200 4822 
\"http://www.tbray.org/ongoing/When/200x/2003/05/06/2000Pix\" \"Mozilla/5.0 ;
(Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 
Firefox/1.5.0.12\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:45:59 
-0700] \"GET /ongoing/serif.css HTTP/1.1\" 200 4808 
\"http://www.tbray.org/ongoing/When/200x/2003/05/06/2000Pix\" \"Mozilla/5.0 ;
(Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 
Firefox/1.5.0.12\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:45:59 
-0700] \"GET /ongoing/ongoing.js HTTP/1.1\" 200 6688 
\"http://www.tbray.org/ongoing/When/200x/2003/05/06/2000Pix\" \"Mozilla/5.0 ;
(Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 
Firefox/1.5.0.12\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:46:00 -0700] \"GET 
/ongoing/door60.jpg HTTP/1.0\" 200 137200 
\"http://www.tbray.org/ongoing/When/200x/2007/06/15/Cameras\" \"Mozilla/4.0 ;
(compatible; MSIE 6.0; Windows NT 5.1; SV1)\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:46:00 -0700] \"GET 
/ongoing/When/200x/2007/06/15/IMGP5832.png HTTP/1.0\" 200 131839 
\"http://www.tbray.org/ongoing/When/200x/2007/06/15/Cameras\" \"Mozilla/4.0 ;
(compatible; MSIE 6.0; Windows NT 5.1; SV1)\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:46:00 
-0700] \"GET /ongoing/When/200x/2003/05/06/Rune.png HTTP/1.1\" 200 143944 
\"http://www.tbray.org/ongoing/When/200x/2003/05/06/2000Pix\" \"Mozilla/5.0 ;
(Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 
Firefox/1.5.0.12\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:46:00 
-0700] \"GET /ongoing/When/200x/2003/05/06/Glacier.png HTTP/1.1\" 200 78117 
\"http://www.tbray.org/ongoing/When/200x/2003/05/06/2000Pix\" \"Mozilla/5.0 ;
(Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 
Firefox/1.5.0.12\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:46:00 
-0700] \"GET /ongoing/When/200x/2003/05/06/-big/Glacier.jpg HTTP/1.1\" 403 
325 
\"http://images.google.com/imgres?imgurl=http://www.tbray.org/ongoing/When/200x/2003/05/06/-big/Glacier.jpg&imgrefurl=http://www.tbray.org/ongoing/When/200x/2003/05/06/2000Pix&h=642&w=960&sz=298&tbnid=vrql887CTfKbeM:&tbnh=99&tbnw=148&hl=en&um=1&prev=/images%3Fq%3Dglacier%2Bbay%26start%3D20%26ndsp%3D20%26svnum%3D10%26um%3D1%26hl%3Den%26client%3Dfirefox-a%26rls%3Dorg.mozilla:en-US:official%26sa%3DN&frame=small\";
 \"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) 
Gecko/20070508 Firefox/1.5.0.12\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:46:00 
-0700] \"GET /ongoing/Feed.png HTTP/1.1\" 200 786 
\"http://www.tbray.org/ongoing/When/200x/2003/05/06/2000Pix\" \"Mozilla/5.0 ;
(Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 
Firefox/1.5.0.12\""
+     "58x80x72x227.ap58.ftth.ucom.ne.jp - - [17/Jun/2007:22:46:00 -0700] 
\"GET /ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"RssBar/1.29\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:46:01 
-0700] \"GET /favicon.ico HTTP/1.1\" 200 318 \"-\" \"Mozilla/5.0 (Windows; U; 
Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 Firefox/1.5.0.12\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:46:01 -0700] \"GET 
/ongoing/in-feed.xml HTTP/1.0\" 200 977 
\"http://www.tbray.org/ongoing/When/200x/2007/06/15/Cameras\" \"Mozilla/4.0 ;
(compatible; MSIE 6.0; Windows NT 5.1; SV1)\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:46:01 -0700] \"GET 
/ongoing/picInfo.xml?o=http://www.tbray.org/ongoing/When/200x/2007/06/15/Cameras
 HTTP/1.0\" 200 196 
\"http://www.tbray.org/ongoing/When/200x/2007/06/15/Cameras\" \"Mozilla/4.0 ;
(compatible; MSIE 6.0; Windows NT 5.1; SV1)\""
+     "c-24-21-119-91.hsd1.mn.comcast.net - - [17/Jun/2007:22:46:01 -0700] 
\"GET /ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"Windows-RSS-Platform/1.0 
(MSIE 7.0; Windows NT 6.0)\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:46:01 
-0700] \"GET /ongoing/door60.jpg HTTP/1.1\" 200 137200 
\"http://www.tbray.org/ongoing/serif.css\" \"Mozilla/5.0 ;(Windows; U; Windows 
NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 Firefox/1.5.0.12\""
+     "c-24-4-61-178.hsd1.ca.comcast.net - - [17/Jun/2007:22:46:01 -0700] 
\"GET /ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"AppleSyndication/54\""
+     "mt501023.inktomisearch.com - - [17/Jun/2007:22:46:02 -0700] \"GET 
/ongoing/When/200x/2007/ HTTP/1.0\" 304 - \"-\" \"Mozilla/5.0 (compatible; 
Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)\""
+     "70-56-93-224.tukw.qwest.net - - [17/Jun/2007:22:46:03 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"Vienna/2.1.2.2110\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:46:03 
-0700] \"GET /ongoing/When/200x/2003/05/06/Glacier.png HTTP/1.1\" 206 150739 
\"http://www.tbray.org/ongoing/When/200x/2003/05/06/2000Pix\" \"Mozilla/5.0 ;
(Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 
Firefox/1.5.0.12\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:46:03 
-0700] \"GET /ongoing/When/200x/2003/05/06/Rune.png HTTP/1.1\" 206 149824 
\"http://www.tbray.org/ongoing/When/200x/2003/05/06/2000Pix\" \"Mozilla/5.0 ;
(Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 
Firefox/1.5.0.12\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:46:03 
-0700] \"GET /ongoing/Feed.png HTTP/1.1\" 200 786 
\"http://www.tbray.org/ongoing/When/200x/2003/05/06/2000Pix\" \"Mozilla/5.0 ;
(Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 
Firefox/1.5.0.12\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:46:04 
-0700] \"GET 
/ongoing/picInfo.xml?o=http://www.tbray.org/ongoing/When/200x/2003/05/06/2000Pix
 HTTP/1.1\" 200 196 \"-\" \"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; 
rv:1.8.0.12) Gecko/20070508 Firefox/1.5.0.12\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:46:04 
-0700] \"GET /ongoing/in-feed.xml HTTP/1.1\" 200 977 \"-\" \"Mozilla/5.0 
(Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 
Firefox/1.5.0.12\""
+     "adsl-074-229-029-232.sip.mia.bellsouth.net - - [17/Jun/2007:22:46:04 
-0700] \"GET /ongoing/door60.jpg HTTP/1.1\" 200 137200 
\"http://www.tbray.org/ongoing/serif.css\" \"Mozilla/5.0 ;(Windows; U; Windows 
NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 Firefox/1.5.0.12\""
+     "sub19-247.member.dsl-only.net - - [17/Jun/2007:22:46:04 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.1\" 200 69717 \"-\" \"Mozilla/4.0 (compatible; 
MSIE 7.0; Windows NT 5.1; Tablet PC 1.7; .NET CLR 1.0.3705; .NET CLR 
2.0.50727; InfoPath.2; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; MSOffice 
12)\""
+     "82-208-115-51.cs3-ats34-dzer.dialup.mts-nn.ru - - 
[17/Jun/2007:22:46:05 -0700] \"GET /ongoing/When/200x/2007/06/17/Fathers-Day 
HTTP/1.1\" 200 8251 \"http://blogs.sun.com/\" \"Mozilla/5.0 ;(Windows; U; Win 
9x 4.90; ru; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4 Mnenhy/0.7.5.666\""
+     "ras75-3-82-225-164-105.fbx.proxad.net - - [17/Jun/2007:22:46:06 -0700] 
\"GET /ongoing/When/200x/2007/06/17/Fathers-Day HTTP/1.1\" 200 8251 
\"http://www.tbray.org/ongoing/\" \"Mozilla/5.0 ;(Macintosh; U; Intel Mac OS 
X; en-US; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4\""
+     "mt501023.inktomisearch.com - - [17/Jun/2007:22:46:06 -0700] \"GET 
/ongoing/sans.css HTTP/1.0\" 200 4822 
\"http://www.tbray.org/ongoing/When/200x/2007/\" \"Mozilla/5.0 ;(compatible; 
Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)\""
+     "ras75-3-82-225-164-105.fbx.proxad.net - - [17/Jun/2007:22:46:07 -0700] 
\"GET /ongoing/sans.css HTTP/1.1\" 304 - 
\"http://www.tbray.org/ongoing/When/200x/2007/06/17/Fathers-Day\" ;
\"Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.4) 
Gecko/20070515 Firefox/2.0.0.4\""
+     "ras75-3-82-225-164-105.fbx.proxad.net - - [17/Jun/2007:22:46:07 -0700] 
\"GET /ongoing/serif.css HTTP/1.1\" 304 - 
\"http://www.tbray.org/ongoing/When/200x/2007/06/17/Fathers-Day\" ;
\"Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.4) 
Gecko/20070515 Firefox/2.0.0.4\""
+     "ras75-3-82-225-164-105.fbx.proxad.net - - [17/Jun/2007:22:46:07 -0700] 
\"GET /ongoing/ongoing.js HTTP/1.1\" 304 - 
\"http://www.tbray.org/ongoing/When/200x/2007/06/17/Fathers-Day\" ;
\"Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.4) 
Gecko/20070515 Firefox/2.0.0.4\""
+     "ras75-3-82-225-164-105.fbx.proxad.net - - [17/Jun/2007:22:46:07 -0700] 
\"GET /ongoing/potd.png HTTP/1.1\" 304 - 
\"http://www.tbray.org/ongoing/When/200x/2007/06/17/Fathers-Day\" ;
\"Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.4) 
Gecko/20070515 Firefox/2.0.0.4\""
+     "82-208-115-51.cs3-ats34-dzer.dialup.mts-nn.ru - - 
[17/Jun/2007:22:46:07 -0700] \"GET /ongoing/sans.css HTTP/1.1\" 200 4822 
\"http://www.tbray.org/ongoing/When/200x/2007/06/17/Fathers-Day\" ;
\"Mozilla/5.0 (Windows; U; Win 9x 4.90; ru; rv:1.8.1.4) Gecko/20070515 
Firefox/2.0.0.4 Mnenhy/0.7.5.666\""
+     "ras75-3-82-225-164-105.fbx.proxad.net - - [17/Jun/2007:22:46:07 -0700] 
\"GET 
/ongoing/picInfo.xml?o=http://www.tbray.org/ongoing/When/200x/2007/06/17/Fathers-Day
 HTTP/1.1\" 200 196 
\"http://www.tbray.org/ongoing/When/200x/2007/06/17/Fathers-Day\" ;
\"Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.4) 
Gecko/20070515 Firefox/2.0.0.4\""
+     "techmeme.com - - [17/Jun/2007:22:46:11 -0700] \"GET /robots.txt 
HTTP/1.1\" 200 1364 \"-\" \"Mozilla/5.0 (compatible; Wazzup1.0.6706; 
http://70.86.131.10/Wazzup)\""
+     "techmeme.com - - [17/Jun/2007:22:46:11 -0700] \"GET /robots.txt 
HTTP/1.1\" 200 1364 \"-\" \"Mozilla/5.0 (compatible; Wazzup1.0.3199; 
http://70.86.131.10/Wazzup)\""
+     "crm11.image.search.mud.yahoo.net - - [17/Jun/2007:22:46:12 -0700] 
\"GET /ongoing/When/200x/2005/08/05/IMG_3937.png HTTP/1.0\" 200 152739 \"-\" 
\"Yahoo-MMCrawler/3.x (mms dash mmcrawler dash support at yahoo dash inc dot 
com)\""
+     "techmeme.com - - [17/Jun/2007:22:46:12 -0700] \"GET /ongoing/ 
HTTP/1.1\" 200 19032 \"-\" \"Mozilla/5.0 (compatible; Wazzup1.0.7330; 
http://70.86.131.10/Wazzup)\""
+     "techmeme.com - - [17/Jun/2007:22:46:12 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.1\" 200 69717 \"-\" \"Mozilla/5.0 (compatible; 
Wazzup1.0.1212; http://70.86.131.10/Wazzup)\""
+     "dsl081-128-098.nyc1.dsl.speakeasy.net - - [17/Jun/2007:22:46:12 -0700] 
\"GET /ongoing/ongoing.atom HTTP/1.1\" 200 69717 \"-\" \"Mozilla/4.0 
(compatible; MSIE 7.0; Windows NT 5.1; SU 3.002; MSDigitalLocker; .NET CLR 
1.1.4322; InfoPath.2; .NET CLR 2.0.50727; MSOffice 12)\""
+     "pool-71-175-67-187.phlapa.fios.verizon.net - - [17/Jun/2007:22:46:14 
-0700] \"GET /ongoing/When/200x/2004/04/27/RSSticker HTTP/1.1\" 200 5310 
\"-\" \"-\""
+     "pool-71-175-67-187.phlapa.fios.verizon.net - - [17/Jun/2007:22:46:14 
-0700] \"GET /ongoing/When/200x/2004/04/27/-/W3C/DTD%20XHTML%201.1/EN 
HTTP/1.1\" 404 327 \"-\" \"-\""
+     "mt501023.inktomisearch.com - - [17/Jun/2007:22:46:15 -0700] \"GET 
/ongoing/serif.css HTTP/1.0\" 404 4808 
\"http://www.tbray.org/ongoing/When/200x/2007/\" \"Mozilla/5.0 ;(compatible; 
Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)\""
+     "host100.newsgator.com - - [17/Jun/2007:22:46:16 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"NewsGatorOnline/2.0 
(http://www.newsgator.com; 7088 subscribers)\""
+     "80.86.78.228 - - [17/Jun/2007:22:46:16 -0700] \"GET /ongoing/ 
HTTP/1.1\" 304 - \"http://feeds.feedburner.com/imurdock\" \"Sunrise/0.42j ;
(Linux)\""
+     "bzq-88-153-172-148.red.bezeqint.net - - [17/Jun/2007:22:46:19 -0700] 
\"GET /ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"NetNewsWire/2.1b37 (Mac 
OS X; Lite; http://ranchero.com/netnewswire/)\""
+     "208.68.164.11 - - [17/Jun/2007:22:46:20 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.1\" 200 69717 \"-\" \"XML-FeedPP/0.21 
XML-TreePP/0.19 libwww-perl/5.805\""
+     "newest.xs4all.nl - - [17/Jun/2007:22:46:20 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"NetNewsWire/2.1.1 (Mac OS X; 
Lite; http://ranchero.com/netnewswire/)\""
+     "c-24-21-119-91.hsd1.mn.comcast.net - - [17/Jun/2007:22:46:24 -0700] 
\"GET /ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"Mozilla/4.0 (compatible; 
MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; 
InfoPath.2; MSOffice 12)\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:46:24 -0700] \"GET 
/ongoing/When/200x/2007/03/29/Maxed HTTP/1.0\" 200 9583 
\"http://cx1.src.ricoh.co.jp/wordpress/archives/213\" \"Mozilla/4.0 ;
(compatible; MSIE 6.0; Windows NT 5.1; SV1)\""
+     "chello084113131197.4.13.vie.surfer.at - - [17/Jun/2007:22:46:27 -0700] 
\"GET /ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"BlogBridge 5.7 
(http://www.blogbridge.com/) 1.6.0_01\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:46:27 -0700] \"GET 
/ongoing/When/200x/2007/03/29/IMG_0059.png HTTP/1.0\" 200 169356 
\"http://www.tbray.org/ongoing/When/200x/2007/03/29/Maxed\" \"Mozilla/4.0 ;
(compatible; MSIE 6.0; Windows NT 5.1; SV1)\""
+     "c-76-97-239-9.hsd1.ga.comcast.net - - [17/Jun/2007:22:46:27 -0700] 
\"GET /ongoing/ongoing.rss HTTP/1.1\" 301 327 \"-\" \"Mozilla/5.0 (Macintosh; 
U; Intel Mac OS X; en-US; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4\""
+     "c-76-97-239-9.hsd1.ga.comcast.net - - [17/Jun/2007:22:46:27 -0700] 
\"GET /ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"Mozilla/5.0 (Macintosh; 
U; Intel Mac OS X; en-US; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:46:28 -0700] \"GET 
/ongoing/picInfo.xml?o=http://www.tbray.org/ongoing/When/200x/2007/03/29/Maxed
 HTTP/1.0\" 200 196 
\"http://www.tbray.org/ongoing/When/200x/2007/03/29/Maxed\" \"Mozilla/4.0 ;
(compatible; MSIE 6.0; Windows NT 5.1; SV1)\""
+     "c-67-181-218-96.hsd1.ca.comcast.net - - [17/Jun/2007:22:46:29 -0700] 
\"GET /ongoing/ongoing.atom HTTP/1.1\" 301 323 \"-\" \"Mozilla/5.0 (X11; U; 
Linux i686; en-US; rv:1.8.1.4) Gecko/20061201 Firefox/2.0.0.4 
(Ubuntu-feisty)\""
+     "83-131-48-167.adsl.net.t-com.hr - - [17/Jun/2007:22:46:29 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"AppleSyndication/54\""
+     "24-216-68-77.dhcp.stls.mo.charter.com - - [17/Jun/2007:22:46:30 -0700] 
\"GET /ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"NetNewsWire/2.1.1 (Mac 
OS X; http://ranchero.com/netnewswire/)\""
+     "c-67-181-218-96.hsd1.ca.comcast.net - - [17/Jun/2007:22:46:30 -0700] 
\"GET /ongoing/ongoing.atom HTTP/1.1\" 200 69717 \"-\" \"Mozilla/5.0 (X11; U; 
Linux i686; en-US; rv:1.8.1.4) Gecko/20061201 Firefox/2.0.0.4 
(Ubuntu-feisty)\""
+     "82-208-115-51.cs3-ats34-dzer.dialup.mts-nn.ru - - 
[17/Jun/2007:22:46:31 -0700] \"GET /ongoing/serif.css HTTP/1.1\" 404 4808 
\"http://www.tbray.org/ongoing/When/200x/2007/06/17/Fathers-Day\" ;
\"Mozilla/5.0 (Windows; U; Win 9x 4.90; ru; rv:1.8.1.4) Gecko/20070515 
Firefox/2.0.0.4 Mnenhy/0.7.5.666\""
+     "crm11.image.search.mud.yahoo.net - - [17/Jun/2007:22:46:31 -0700] 
\"GET /ongoing/When/200x/2003/12/07/JVaughan.png HTTP/1.0\" 200 189428 \"-\" 
\"Yahoo-MMCrawler/3.x (mms dash mmcrawler dash support at yahoo dash inc dot 
com)\""
+     "cpe0013464a4357-cm001225449bf4.cpe.net.cable.rogers.com - - 
[17/Jun/2007:22:46:31 -0700] \"GET /ongoing/ongoing.atom HTTP/1.1\" 304 - 
\"-\" \"NetNewsWire/2.1.1 (Mac OS X; http://ranchero.com/netnewswire/)\""
+     "m11b.feeds.yandex.net - - [17/Jun/2007:22:46:34 -0700] \"GET 
/robots.txt HTTP/1.1\" 200 1364 \"-\" \"YandexSomething/1.0\""
+     "m11b.feeds.yandex.net - - [17/Jun/2007:22:46:34 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"YandexBlog/0.99.101 
(compatible; DOS3.30; Mozilla/5.0; B; robot) 13 readers\""
+     "c-71-198-185-175.hsd1.ca.comcast.net - - [17/Jun/2007:22:46:35 -0700] 
\"GET /ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"NetNewsWire/2.1 (Mac OS 
X; Lite; http://ranchero.com/netnewswire/)\""
+     "nulgw14.unisys.co.jp - - [17/Jun/2007:22:46:35 -0700] \"GET 
/ongoing/sans.css HTTP/1.1\" 200 4822 \"-\" \"Mozilla/4.0 (compatible;)\""
+     "cpe001310d25021-cm001225708864.cpe.net.cable.rogers.com - - 
[17/Jun/2007:22:46:36 -0700] \"GET /ongoing/ongoing.atom HTTP/1.1\" 304 - 
\"-\" \"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 
2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506; InfoPath.2; Tablet PC 
2.0; .NET CLR 3.5.20404; MSOffice 12)\""
+     "c-24-5-76-35.hsd1.ca.comcast.net - - [17/Jun/2007:22:46:36 -0700] 
\"GET /ongoing/ongoing.atom HTTP/1.1\" 200 69717 \"-\" \"NetNewsWire/2.1.1 
(Mac OS X; http://ranchero.com/netnewswire/)\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:46:38 -0700] \"GET 
/ongoing/ongoing.rss HTTP/1.0\" 301 315 \"-\" \"FreshReader/2.0.07041100 (id: 
549f074b; lang: ja; http://www.freshreader.com/; 1 subscribers)\""
+     "proxy.ricoh.co.jp - - [17/Jun/2007:22:46:39 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.0\" 200 69717 \"-\" \"FreshReader/2.0.07041100 
(id: 549f074b; lang: ja; http://www.freshreader.com/; 1 subscribers)\""
+     "82-208-115-51.cs3-ats34-dzer.dialup.mts-nn.ru - - 
[17/Jun/2007:22:46:39 -0700] \"GET /ongoing/Feed.png HTTP/1.1\" 200 786 
\"http://www.tbray.org/ongoing/When/200x/2007/06/17/Fathers-Day\" ;
\"Mozilla/5.0 (Windows; U; Win 9x 4.90; ru; rv:1.8.1.4) Gecko/20070515 
Firefox/2.0.0.4 Mnenhy/0.7.5.666\""
+"201-34-233-57.bsace704.dsl.brasiltelecom.net.br - - [17/Jun/2007:22:46:41 
-0700] \"GET /ongoing/When/200x/2003/09/03/McLaren HTTP/1.1\" 200 6610 \"-\" 
\"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\""
+"1a.c3.5d45.static.theplanet.com - - [17/Jun/2007:22:46:43 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.0\" 304 - \"-\" \"Gregarius/0.5.4 
(+http://devlog.gregarius.net/docs/ua)\""
+"p57b646bd.dip0.t-ipconnect.de - - [17/Jun/2007:22:46:44 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.0\" 304 - \"-\" \"NetNewsWire/2.0.1 (Mac OS X; 
http://ranchero.com/netnewswire/)\""
+"p3ee3d6f8.dip.t-dialin.net - - [17/Jun/2007:22:46:46 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.1\" 304 - \"-\" \"NetNewsWire/3.0 (Mac OS X; 
http://ranchero.com/netnewswire/)\""
+"cpc2-swan1-0-0-cust781.swan.cable.ntl.com - - [17/Jun/2007:22:46:48 -0700] 
\"GET /ongoing/When/200x/2003/10/16/Debbie HTTP/1.1\" 200 8244 
\"http://search.virginmedia.com/results/index.php?channel=other&q=debbie+does&cr=\";
 \"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 
(compatible; MSIE 6.0; Windows NT 5.1; SV1) )\""
+"cpc2-swan1-0-0-cust781.swan.cable.ntl.com - - [17/Jun/2007:22:46:48 -0700] 
\"GET /ongoing/sans.css HTTP/1.1\" 200 4822 
\"http://www.tbray.org/ongoing/When/200x/2003/10/16/Debbie\" \"Mozilla/4.0 ;
(compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; 
Windows NT 5.1; SV1) )\""
+"cpc2-swan1-0-0-cust781.swan.cable.ntl.com - - [17/Jun/2007:22:46:48 -0700] 
\"GET /ongoing/serif.css HTTP/1.1\" 200 4808 
\"http://www.tbray.org/ongoing/When/200x/2003/10/16/Debbie\" \"Mozilla/4.0 ;
(compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; 
Windows NT 5.1; SV1) )\""
+"cpc2-swan1-0-0-cust781.swan.cable.ntl.com - - [17/Jun/2007:22:46:48 -0700] 
\"GET /ongoing/ongoing.js HTTP/1.1\" 200 6688 
\"http://www.tbray.org/ongoing/When/200x/2003/10/16/Debbie\" \"Mozilla/4.0 ;
(compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; 
Windows NT 5.1; SV1) )\""
+"slim07.kataweb.it - - [17/Jun/2007:22:46:48 -0700] \"GET 
/ongoing/ongoing.rss HTTP/1.1\" 301 322 \"-\" \"Java/1.4.2_08\""
+"cpc2-swan1-0-0-cust781.swan.cable.ntl.com - - [17/Jun/2007:22:46:48 -0700] 
\"GET /ongoing/Feed.png HTTP/1.1\" 200 786 
\"http://www.tbray.org/ongoing/When/200x/2003/10/16/Debbie\" \"Mozilla/4.0 ;
(compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; 
Windows NT 5.1; SV1) )\""
+"slim07.kataweb.it - - [17/Jun/2007:22:46:48 -0700] \"GET 
/ongoing/ongoing.rss HTTP/1.1\" 301 327 \"-\" \"Java/1.4.2_08\""
+"cpc2-swan1-0-0-cust781.swan.cable.ntl.com - - [17/Jun/2007:22:46:49 -0700] 
\"GET /ongoing/potd.png HTTP/1.1\" 200 80265 
\"http://www.tbray.org/ongoing/When/200x/2003/10/16/Debbie\" \"Mozilla/4.0 ;
(compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; 
Windows NT 5.1; SV1) )\""
+"host86-143-230-228.range86-143.btcentralplus.com - - [17/Jun/2007:22:46:49 
-0700] \"GET /ongoing/ongoing.atom HTTP/1.1\" 200 69717 \"-\" 
\"NetNewsWire/2.1.1 (Mac OS X; Lite; http://ranchero.com/netnewswire/)\""
+"slim07.kataweb.it - - [17/Jun/2007:22:46:49 -0700] \"GET 
/ongoing/ongoing.atom HTTP/1.1\" 200 69717 \"-\" \"Java/1.4.2_08\""
+"cpc2-swan1-0-0-cust781.swan.cable.ntl.com - - [17/Jun/2007:22:46:49 -0700] 
\"GET /ongoing/door60.jpg HTTP/1.1\" 200 137200 
\"http://www.tbray.org/ongoing/When/200x/2003/10/16/Debbie\" \"Mozilla/4.0 ;
(compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; 
Windows NT 5.1; SV1) )\""
+"cpc2-swan1-0-0-cust781.swan.cable.ntl.com - - [17/Jun/2007:22:46:50 -0700] 
\"GET /favicon.ico HTTP/1.1\" 200 318 \"-\" \"Mozilla/4.0 (compatible; MSIE 
7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) 
)\""
+])
+)
+
Index: src/org/tbray/JOverhead.java
===================================================================
--- src/org/tbray/JOverhead.java        (revision 3)
+++ src/org/tbray/JOverhead.java        (revision 4)
@@ -5,6 +5,7 @@
 
 package org.tbray;
 
+import java.io.File;
 import java.io.FileInputStream;
 import java.nio.CharBuffer;
 import java.nio.MappedByteBuffer;
@@ -18,12 +19,22 @@
  */
 public class JOverhead {
 
-    private static void blok(FileChannel channel, long offset, int size) 
throws Exception {
-        MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 
offset, size);
-        CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
-        CharBuffer chars = decoder.decode(buffer);
-        char c = chars.get(chars.length() - 10);
-        System.out.println("C=" + c);
+    static Charset charset = Charset.forName("UTF-8");
+
+    private static int[] blok(FileInputStream in, int size) throws Exception 
{
+        byte[] buffer = new byte[size];
+        int read = in.read(buffer);
+        String text = new String(buffer, 0, read, charset);
+        int lines = 0;
+        int chars = 0;
+        for (int last = 0, next = text.indexOf('\n', last); next >= 0; next 
= text.indexOf('\n', last)) {
+            String line = text.substring(last, next);
+            lines++;
+            chars += line.length();
+            last = next + 1;
+        }
+        int[] ret = { lines, chars };
+        return ret;
     }
 
     /**
@@ -31,19 +42,27 @@
      */
     public static void main(String[] args) throws Exception {
         // arg is filename
-        FileChannel channel = (new FileInputStream(args[0])).getChannel();
-        long dataSize = channel.size();
+        File file = new File(args[0]);
+        FileInputStream in = new FileInputStream(file);
+        long dataSize = file.length();
         int blockSize = 10 * 1024 * 1024;
         if (args.length > 1)
             blockSize = Integer.parseInt(args[1]) * 1024 * 1024;
         long blockCount = dataSize / blockSize;
         int tailSize = (int) (dataSize % blockSize);
+        long lines = 0, chars = 0;
 
+        int[] r;
         for (long i = 0; i < blockCount; i++) {
             System.out.println("B " + i);
-            blok(channel, i * blockSize, blockSize);
+            r = blok(in, blockSize);
+            lines += r[0];
+            chars += r[1];
         }
-        blok(channel, blockCount * blockSize, tailSize);
+        r = blok(in, tailSize);
+        lines += r[0];
+        chars += r[1];
+        System.out.println("L=" + lines + " C=" + chars);
     }
 
 }
Index: src/org/tbray/popular.clj
===================================================================
--- src/org/tbray/popular.clj   (revision 3)
+++ src/org/tbray/popular.clj   (revision 4)
@@ -1,10 +1,5 @@
+(ns org.tbray.popular)
 
-(ns org.tbray.paralines
-  ;(:require )
-  ;(:use )
-  ;(:import )
-  )
-
 (def re #"GET /ongoing/When/\d\d\dx/(\d\d\d\d/\d\d/\d\d/[^ .]+) ")
  
 (defn record [target accum]
@@ -14,7 +9,7 @@
       (assoc accum target 1))
     { target 1 }))
 
-(defn proc-line [ line so-far accum]
+(defn proc-line [line so-far accum]
   (if line
     (if-let [[_ target] (re-find re line)]
       (record target accum)
Index: src/org/tbray/read_lines.clj
===================================================================
--- src/org/tbray/read_lines.clj        (revision 0)
+++ src/org/tbray/read_lines.clj        (revision 4)
@@ -0,0 +1,104 @@
+(ns org.tbray.read-lines
+  (:import (java.io FileInputStream) (java.nio.charset Charset)))
+
+(declare dispatch proc-block)
+(def *charset* (. java.nio.charset.Charset forName "UTF-8"))
+
+(defn frag
+  "fragments is a map whose keys are of the form (str index :front|:back)"
+  [fragments fragment index front-back]
+  (dosync
+    (ref-set fragments (assoc @fragments (str index front-back) (new String 
fragment)))))
+
+(defn join-fragments [fragments-in params]
+  (loop [fragments fragments-in accum nil]
+    (if (not (empty? fragments))
+      (let [[key frag] (first fragments)
+            [istring fb] (. #":" split key)
+            index (new Integer istring)
+            is-front (= fb "front")
+            other-key (if is-front (str (dec index) ":back") (str (inc 
index) ":front"))
+            other (fragments other-key)
+            line (if is-front (str other frag) (str frag other))
+            next-accum ((params :per-line) accum line) ]
+        (recur (dissoc fragments key other-key) next-accum))
+      ((params :done-lines) accum))))
+
+(defn count-down [so-far params]
+  (let [processed (inc so-far)]
+    (if (> processed (params :block-count))
+      (let [fragments (params :fragments)] ; yep, all finished
+        (join-fragments (deref fragments) params)
+        ((params :all-done))
+        (. System exit 0))
+      processed)))
+
+(defn proc-block [bytes index params last]
+  (println (str "Block " index))
+  (let [text (new String bytes *charset*)
+        trailing-nl (. text endsWith "\n")
+        chunks (. #"\n" split text)
+        front (first chunks)
+        lc (get chunks (dec (count chunks))) ; (last chunks) tickles a 
Clojure 1.0 bug
+        back (if trailing-nl "" lc)
+        lines (if trailing-nl (rest chunks) (butlast (rest chunks)))
+        accumulator (reduce (params :per-line) nil lines) ] ; all the work 
happens here
+
+    ((params :done-lines) accumulator) ; tell user-provided function this 
thread done
+    (frag (params :fragments) front index :front) ; save front/back fragments
+    (if (not last)
+      (frag (params :fragments) back index :back))
+
+    (send (params :processed) count-down params)   ; record one more block 
done
+    (send (params :index-agent) dispatch params))) ; tell dispatcher we're 
done
+
+(defn dispatch [ index params ] ; reading is single-threaded here
+  (let [next (inc index) block-count (params :block-count)]
+    (if (<= index block-count)
+      (let [last (= index block-count)
+            size (if last (params :tail-size) (params :block-size))
+            buffer (make-array Byte/TYPE size)]
+        (. (params :input) read buffer)
+        (.start (new Thread #(proc-block buffer index params last)))
+        next)
+      index)))
+
+(defn read-lines
+  "Reads the named file and feeds the lines one at a time to the function
+'destination', which will be called in parallel on many threads with three
+arguments, the first being a line from the file, the second 'user-data',
+the third an accumulator, whose value will be nil on the first call in
+any given thread.  The destination function's return value will appear on the
+next call as its accumulator argument.  If the function is called with a nil
+value for the first (line) argument, that signals the final call in some 
given
+thread, so that the function may choose to do wind-up and reporting work.
+
+When all the lines have been processed, the the 'all-done' function will be
+called with 'user-data' as its single argument.  The 'destination' function
+will be called on multiple threads in parallel, so its logic must be
+thread-safe.  There is no guarantee in which order the lines from the file
+will be processed.  The 'settings' argument is a map; the default values for 
the
+number of threads and file block-size may be overridden with the :width and
+:block-size values respectively."
+  [file-name destination all-done user-data settings]
+  (let [block-size (or (settings :block-size) (* 10 1024 1024))
+        input (new FileInputStream file-name)
+        data-size (. (new java.io.File file-name) length)
+        fragments (ref {})
+        block-count (quot data-size block-size)
+        thread-count (max 1 (min block-count (or (settings :width) 10)))
+        tail-size (mod data-size block-size)
+        index (agent 0)
+        params {:block-count block-count :block-size block-size :tail-size 
tail-size
+                :input input :processed (agent 0)
+                :per-line (fn [accum #^String line] (destination (new String 
line) user-data accum))
+                :done-lines (fn [accum] (destination nil user-data accum))
+                :all-done (fn [] (all-done user-data))
+                :fragments fragments
+                :index-agent index }]
+
+    (frag fragments "" -1 :back)  ; prime the fragments pump
+    (doseq [_ (repeat thread-count 0)]
+      (send index dispatch params))
+    (. (. Thread currentThread) join)))
+

Property changes on: .
___________________________________________________________________
Added: svn:ignore
   + build







[divide-and-conquer~concur-next:4] State of play as of Dec. 9th.

TimBray 12/10/2009
  • Mysql
  • Glassfish
  • Jruby
  • Rails
  • Nblogo
Terms of Use; Privacy Policy;
© 2010, Oracle Corporation and/or its affiliates
(revision 20120518.3c65429)
 
 
Close
loading
Please Confirm
Close