Thanks for your reply, you are right, the server close before all clients completed. (i was suppose that dorun waits for the threads results before returning.)
Anyway, i was trying to emulate the real problem with no success here. I 'll try to describe it. The clients connect to an extrernal application via socket with a fixed protocol requesting some information for an object indexed with <id> and wait a confirmation response (not the information) from the external application. The external application connects to my socket-server returns that information, waits for a "received ok" confirmation and then respond to the client with "sending ok". Each client need to call a different function on information data so, in my clients code: put the id and the function to call on data, in my server reference variable connect to external application sending the id. waiting a confirmation response from the external application. in my server code: read the id and information from the external application. respond to the external application with "received ok" lookup that id in reference variable and call the function on data. The problem is that in my testing environment (20 concurent client request repeated 200 times) the server cant find some ids in reference variable.(1 or 2 in 1000). I suspect that i loose those ids because, on high server load, the time to send the id to the external application and receivce the response to server is less that the time needed for the server thread to see the updated value of reference. (is there a maximum time guarantee for content switch of referenced variables?) The solution i gave is a busy loop with a timeout until the server thread finds the id. But the timeout is arbitrary and depends on server load. PS: the flow of information can't be changed because of the fixed communication protocol. On Jun 15, 4:13 pm, sross <ros...@gmail.com> wrote: > On Jun 14, 12:20 am, vmargioulas <vxm...@gmail.com> wrote: > > > > > In the example below 256 clients threads put a byte (0-255) to server- > > socket reference var "items", > > then connect to server-socket, write the same byte to socket stream > > and close the connection. > > The server connections threads reads a byte from the socket stream and > > remove it from the var "items". > > At the end of the run i expect the var items to be empty but it is > > not. > > It 's contains a random number of bytes. > > Where is the error? > > > (ns > > test-dosync > > (:import (java.net Socket)) > > (:use clojure.contrib.server-socket)) > > > (def server > > (let [items (ref nil) > > server-ref (ref nil) > > server-fn (fn [ins _] > > (let [bt (.read ins)] > > (dosync > > (ref-set items (remove #(= % bt) @items)))))] > > > {:enq (fn [item] (dosync (alter items conj item))) > > :list-items (fn [] @items) > > :start (fn [port] > > (let [socket-server (create-server port server-fn)] > > (dosync > > (ref-set items nil) > > (ref-set server-ref socket-server)))) > > :stop (fn [] (when @server-ref (close-server @server-ref))) > > })) > > > (defn start-server [port] ((:start server) port)) > > (defn stop-server [] ((:stop server))) > > (defn enq [id] ((:enq server) id)) > > (defn list-items [] ((:list-items server))) > > > (defn client-fn [port #^Byte byte-to-send] > > #(let [socket (Socket. "localhost" port) > > outs (.getOutputStream socket)] > > (try > > (do > > (enq byte-to-send) > > (doto outs (.write byte-to-send) (.flush))) > > (finally > > (.close socket))))) > > > (defn run-test [] > > (try > > (let [port 10002] > > (start-server port) > > (dorun (apply pcalls (map #(client-fn port %) (range 256))))) > > (finally (stop-server))) > > (list-items)) > > This is probably a lot simpler than you may think; > > What is happening here is that your run-test function is returning > before the removes have been run since the client functions do not > wait for confirmation from the server before returning. This can > result in ordering like the following > (with 2 client threads) > > Client 1 enqueues byte > Client 1 writes byte and flushes > Client 2 enqueues byte > Client 2 writes byte and flushes > Server Thread for Client1 reads byte > Server Thread for Client2 reads byte > Server gets stopped > run-test returns (0 1) > Server Thread for Client1 removes byte > Server Thread for Client2 removes byte. > > Of course this is only an example of a multitude of ways that these > can combine, you can add a couple of logging > statements to your functions to see when these things are happening, > and I think you may be quite surprised at > the different orderings that can arise, but remember to take them with > a grain of salt as output isn't immediate either ;) > > The crux here is that your are relying on the server functions running > to completion but you are not waiting on the client > side to confirm that this has happened. > > - sean --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---