interacting with a "busy" newlisp server with another prgrm

Started by nallen05, January 15, 2010, 12:17:42 AM

Previous topic - Next topic

nallen05

So if I start a newlisp server


newlisp -c -d 4711

and I connect to it with client program #1 and it does stuff (like responding to a request for information)


echo "(begin (sleep 10000) 'return-stuff)" | nc 127.0.0.1 4711

and then I suspect something is wrong inside the newlisp server because the output or behavior of client program #1 doesn't seem right, I can send code to the place the newlisp server is listening to (assuming I know it) from client program #2 (like emacs) to debug it


echo '(symbols)' | nc 127.0.0.1 4711

when I try (on my mac, OS X 10.5.8) this client program #2 seems to correctly block until client program #1 gets its answer (assuming #1 exits) then makes its request



My question: is there a better way i should be doing this? (motivation: I want to be able to "debug" a running newlisp server in the least hacky way posible)

Lutz

As of my experience, the best on any platform is, to use either telnet:


~> telnet 127.0.0.1 4711
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
(+ 1 2 3 4)
10
(symbols)
(! != $ $0 $1 $10 $11 $12 $13 $14 $15 $2 $3 $4 $5 $6 $7 $8 $9 $args $idx $it $main-args
 % & * + - / : < << <= = > >= >> ? @ Class MAIN NaN? Tree ^ abort abs acos acosh
 add address amb and append append-file apply args array array-list array? asin asinh
...
unify unique unless unpack until upper-case utf8 utf8len uuid wait-pid when while
 write-buffer write-char write-file write-line xfer-event xml-error xml-parse xml-type-tags
 zero? | ~)


or 'net-eval' from another newLISP instance:


> (net-eval "localhost" 4711 '(+ 1 2 3 4 5))
15
>


You also can use 'net-eval' from the shell command-line this way:


newlisp -e '(net-eval "localhost" 4711 "(symbols)")'



I have used nc too, and there is a util/nclocal.c in the source distribution to test servers on local-domain UNIX sockets, but there is a lot less typing  when using above methods.



Also note, that all of the above methods only test the command-line protocol mode used in 'net-eval'. To test HTTP protocol mode of newLISP server, you would need either a web-browser, or you can do it interactively too from a telnet client or a second newLISP instance:


GET /

then hit the enter-key twice.



Note that most of the above is also explained in the users manual and here:



http://www.newlisp.org/downloads/CodePatterns.html#toc-21">http://www.newlisp.org/downloads/CodePa ... tml#toc-21">http://www.newlisp.org/downloads/CodePatterns.html#toc-21



ps: edited for forgotten single quote before net-eval expression

cormullion

It's cool. But just out of curiousity/pedanticism, what's the difference between these two:


> (net-eval "192.168.0.9" 4711 (+ 1 2 3 4))
10
> (net-eval "192.168.0.9" 4711 '(+ 1 2 3 4))
10


My understanding from the manual is that the first example's sum is evaluated locally, the second example remotely? So then your


(net-eval "localhost" 4711 (+ 1 2 3 4 5))

should be


(net-eval "localhost" 4711 '(+ 1 2 3 4 5))

(if I'm right!) :)

Lutz

I forgot a single quote in my example (now edited).



Since version 10.1.1 the expression in 'net-eval' can be given without the double-quotes as a short-cut, but then would have to carry a single quote.



The ambiguity you are seeing is really is not there:


> (net-eval "localhost" 4711 '(set 'x (+ 3 4)))
7
> x
nil
> (net-eval "localhost" 4711 (set 'x (+ 5 6)))
11
> x
11
>


In the first case the expression is evaluated remotely in the second case the expression is evaluated locally and merely the constant 11 is sent out for evaluation and evaluating to itself.



If this is confusing, just double quote the expressions as always required before version 10.1:


> (net-eval "localhost" 4711 "'(+ 1 2 3 4)")
(+ 1 2 3 4)

nallen05

Thanks for your reply Lutz



The posts above give me good ideas on how to approach the problem. It looks like: If I want to "stop the world" and critically debug the server I can telnet in (since it seems to block other programs from accessing). But if I just want to get some data from the server here and there I can go with the NET-EVAL approach



I guess my inspiration for this question was the concurrency issue. If I have a server that is expecting to respond to many frequent queries from client program #1, and I want to "inspect" it from client program #2, is it safe to make a request to the IP and port the server is listening to at any time, relying on the mechanisms in place to prevent simultaneous requests from the two programs from interfering with each other?

Lutz

There is only one thread in newLISP server. Each 'net-eval' request is a closed transaction. As long as a request from client#1 is being worked on, client#2 is waiting. They will not step on each other's feet, but clients should make their timeouts long enough when sending requests to a heavily loaded server.



If your server doesn't need to be state-full, and you are on UNIX, you could run newLISP server as an inetd or xinetd demon. The Users Manual and CodePatterns Manual describe how this is done. When running as an inetd demon a new server instance will be started with each request. Because newLISP is so small and starts up quickly, you could have hundreds of instances running at the same time.



If you need to run a state-full server but requests are lengthy in nature, consider to run multiple servers on several addresses/ports and have a load balancer distributing requests. Depending on the nature of your requests you also could consider caching results.



If you can split up a lengthy request into multiple shorter ones and consolidate the results, this is known as a "Map Reduce" -technique. There is an example how to do this here:



http://www.newlisp.org/syntax.cgi?code/mapreduce.txt">http://www.newlisp.org/syntax.cgi?code/mapreduce.txt



Map Reduce works also well on a single computer, if it is equipped with a multicore CPU.