Hi all - I'm in the process of writing a proxy for MySQL in Clojure,
and until now everything has been going smoothly. My project has
reached the point where it can shuffle data up and down the wire
between client and server with accurate results, but I'm running into
a strange issue. I've noticed that when a certain result size is
reached, (exactly 138 rows in this case), I get a malformed packet
response from the client.

Naturally, I assumed this was just an issue with mishandling the data
being sent to and fro somehow, but then I ran into something strange.
In trying to nail down the issue, I wrote a debug macro which inserts
prints a given statement so long as a *debug* variable is set to true.
As soon as I enabled the macro, the problem resolved itself, and the
client returned the appropriate result. After a brief WTF moment, I
decided it might be some kind of timing issue and changed the debug
macro to simply do a Thread.sleep for 100 milliseconds. Again, this
resolved the problem. Finally, I narrowed down the offending code to
the following:

(defn get-result-query [client server state]
  "handle the states necessary to return a standard query result"
  (let [server-response (connection-read server)]
    (Thread/sleep 100) ; !!!!!!!!! remove this, and the function will
sporadically fail !!!!!!!!!
    (connection-write client server-response)
    (cond (and (= state :start) (eof-packet? server-response))
               (recur client server :row-start)
          (and (= state :row-start) (eof-packet? server-response))
               {:state :send-command :server server}
          (error-packet? server-response)
               {:state :send-command :server server}
          :else (recur client server state))))

It seems that reading from the socket without a subsequent pause
introduces problems for some reason. I have no idea why this would
happen unless the data isn't fully down the wire or something along
those lines. For good measure, here's the connection-read function as
well:

(defn connection-read [#^Socket conn]
  "reads data up to the amount specified by the packet header"
  (let [#^InputStream instream (. conn (getInputStream))
        bytes (make-array (. Byte TYPE) 4)]
    (. instream (read bytes 0 4))
    ; make an array big enough for header + data
    (let [data (make-array (. Byte TYPE)
                           (+ 4 (packet-length? bytes)))]
      (System/arraycopy bytes 0 data 0 4)
      ; read data into the buffer
      (loop [bytes-read (. instream (read data 4 (- (alength data)
4)))]
        ; if we got all the desired data in one pass, return it
        (if (>= bytes-read (- (alength data) 4))
          data
          ; otherwise, read more data
          (let [new-bytes-read (. instream
                                  (read data
                                        bytes-read
                                        (- (alength data) bytes-
read)))]
            (if (== new-bytes-read -1)
              data
              (recur (+ bytes-read new-bytes-read)))))))))

If anybody has any suggestions to why this would be happening, I'd
really appreciate it. I intend to release this project OSS when it's
fully functional, and this is one of the few roadblocks in my way.

Thanks,
Travis
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to