Page 1 of 1

interacting with a "busy" newlisp server with another prgrm

Posted: Fri Jan 15, 2010 8:17 am
by nallen05
So if I start a newlisp server

Code: Select all

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

Code: Select all

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

Code: Select all

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)

Re: interacting with a "busy" newlisp server with another prgrm

Posted: Fri Jan 15, 2010 12:35 pm
by Lutz
As of my experience, the best on any platform is, to use either telnet:

Code: Select all

~> 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:

Code: Select all

> (net-eval "localhost" 4711 '(+ 1 2 3 4 5))
15
> 
You also can use 'net-eval' from the shell command-line this way:

Code: Select all

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:

Code: Select all

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/CodePa ... tml#toc-21

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

Re: interacting with a "busy" newlisp server with another prgrm

Posted: Fri Jan 15, 2010 3:11 pm
by cormullion
It's cool. But just out of curiousity/pedanticism, what's the difference between these two:

Code: Select all

> (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

Code: Select all

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

Code: Select all

(net-eval "localhost" 4711 '(+ 1 2 3 4 5))
(if I'm right!) :)

Re: interacting with a "busy" newlisp server with another prgrm

Posted: Fri Jan 15, 2010 4:30 pm
by 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:

Code: Select all

> (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:

Code: Select all

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

Re: interacting with a "busy" newlisp server with another prgrm

Posted: Fri Jan 15, 2010 7:18 pm
by 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?

Re: interacting with a "busy" newlisp server with another prgrm

Posted: Fri Jan 15, 2010 9:38 pm
by 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

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