Michal D. | 21 Dec 18:07 2010
Picon

Multiple xml http request GET's

Hi,

I'm trying to write a fairly simple AJAX multiplayer game in Yaws.  I spawn a seperate process to handle the server state across all clients.  There are two .yaws files, both called from JavaScript by xml http request objects via GET.

submit.yaws - query string holds a an action performed by the player (affects state server, client ignores any response).
request.yaws - subscribes to state server modification notifications, then wais for a message from the state server with the new state.

The problem is that once submit.yaws is accessed a process dies (different pid from processes handling submit.yaws or request.yaws). After this, the request.yaws seems to hang and no new updates come in. The process that dies shows up with the following message:

=ERROR REPORT==== 21-Dec-2010::12:03:56 ===
Yaws process died: {function_clause,[{yaws_server,binary_size,[0,<0.71.0>]},
                                     {yaws_server,binary_size,2},
                                     {yaws_server,deliver_accumulated,5},
                                     {yaws_server,finish_up_dyn_file,2},
                                     {yaws_server,aloop,3},
                                     {yaws_server,acceptor0,2},
                                     {proc_lib,init_p_do_apply,3}]}

Any hints on what's going on?

Please contact me if something is not clear.

Cheers,

Michal




------------------------------------------------------------------------------
Forrester recently released a report on the Return on Investment (ROI) of
Google Apps. They found a 300% ROI, 38%-56% cost savings, and break-even
within 7 months.  Over 3 million businesses have gone Google with Google Apps:
an online email calendar, and document program that's accessible from your 
browser. Read the Forrester report: http://p.sf.net/sfu/googleapps-sfnew
_______________________________________________
Erlyaws-list mailing list
Erlyaws-list@...
https://lists.sourceforge.net/lists/listinfo/erlyaws-list
Steve Vinoski | 21 Dec 22:51 2010
Picon

Re: Multiple xml http request GET's

On Tue, Dec 21, 2010 at 12:07 PM, Michal D.
<michal.dobrogost@...> wrote:
> Hi,
>
> I'm trying to write a fairly simple AJAX multiplayer game in Yaws.  I spawn
> a seperate process to handle the server state across all clients.  There are
> two .yaws files, both called from JavaScript by xml http request objects via
> GET.
>
> submit.yaws - query string holds a an action performed by the player
> (affects state server, client ignores any response).
> request.yaws - subscribes to state server modification notifications, then
> wais for a message from the state server with the new state.
>
> The problem is that once submit.yaws is accessed a process dies (different
> pid from processes handling submit.yaws or request.yaws). After this, the
> request.yaws seems to hang and no new updates come in. The process that dies
> shows up with the following message:
>
> =ERROR REPORT==== 21-Dec-2010::12:03:56 ===
> Yaws process died: {function_clause,[{yaws_server,binary_size,[0,<0.71.0>]},
>                                      {yaws_server,binary_size,2},
>                                      {yaws_server,deliver_accumulated,5},
>                                      {yaws_server,finish_up_dyn_file,2},
>                                      {yaws_server,aloop,3},
>                                      {yaws_server,acceptor0,2},
>                                      {proc_lib,init_p_do_apply,3}]}
>
> Any hints on what's going on?

I'm guessing you're giving Yaws some bad values to be returned as part
of the response body from your .yaws code. Can you either post your
.yaws code or send me a copy offline?

--steve

------------------------------------------------------------------------------
Forrester recently released a report on the Return on Investment (ROI) of
Google Apps. They found a 300% ROI, 38%-56% cost savings, and break-even
within 7 months.  Over 3 million businesses have gone Google with Google Apps:
an online email calendar, and document program that's accessible from your 
browser. Read the Forrester report: http://p.sf.net/sfu/googleapps-sfnew
Michal D. | 22 Dec 02:41 2010
Picon

Re: Multiple xml http request GET's



On Tue, Dec 21, 2010 at 4:51 PM, Steve Vinoski <vinoski <at> ieee.org> wrote:
On Tue, Dec 21, 2010 at 12:07 PM, Michal D. <michal.dobrogost <at> gmail.com> wrote:
> Hi,
>
> I'm trying to write a fairly simple AJAX multiplayer game in Yaws.  I spawn
> a seperate process to handle the server state across all clients.  There are
> two .yaws files, both called from JavaScript by xml http request objects via
> GET.
>
> submit.yaws - query string holds a an action performed by the player
> (affects state server, client ignores any response).
> request.yaws - subscribes to state server modification notifications, then
> wais for a message from the state server with the new state.
>
> The problem is that once submit.yaws is accessed a process dies (different
> pid from processes handling submit.yaws or request.yaws). After this, the
> request.yaws seems to hang and no new updates come in. The process that dies
> shows up with the following message:
>
> =ERROR REPORT==== 21-Dec-2010::12:03:56 ===
> Yaws process died: {function_clause,[{yaws_server,binary_size,[0,<0.71.0>]},
>                                      {yaws_server,binary_size,2},
>                                      {yaws_server,deliver_accumulated,5},
>                                      {yaws_server,finish_up_dyn_file,2},
>                                      {yaws_server,aloop,3},
>                                      {yaws_server,acceptor0,2},
>                                      {proc_lib,init_p_do_apply,3}]}
>
> Any hints on what's going on?

I'm guessing you're giving Yaws some bad values to be returned as part
of the response body from your .yaws code. Can you either post your
.yaws code or send me a copy offline?

--steve

Hi Steve,

Thanks for taking an interest in my problem.   I created a toy version that will hopefully be easier to debug but it doesn't have exactly the same problem.  Same: sometimes 'reset' will hang the counter.  Different: real page always seems to hang, toy does not crash any processes.  Hopefully it will give you an idea of what's going on though.  I'll send the real code if still necessary.

Sorry for the longish message, this is as much as I could get it down.

=== yaws/request.yaws =========================
<erl>

out(A) ->
    io:put_chars("request.yaws hello\n\n"),

    % Start the game server if it's not running yet.
    ebin:start_server(),

    % Send the request.
    global:send(stateServer, {request, self()}),
    receive Result -> {html, Result} end.

</erl>
=== yaws/submit.yaws =========================
<erl>

out(A) ->
    io:put_chars("submit.yaws hello\n\n"),

    % Start the game server if it's not running yet.
    ebin:start_server(),

    % Send submit.
    global:send(stateServer, submit),
    {html, ""}.

</erl>
=== ebin/ebin.erl ==============================
-module(ebin).
-export([state_server/2, start_server/0]).

term_to_str(T) -> lists:flatten(io_lib:format("~p", [T])).

% Start the game server if it's not running yet.
start_server() ->
    case global:whereis_name(stateServer) of
        undefined ->
                Pid = spawn(ebin, state_server, [0, []]),
                global:register_name(stateServer, Pid),
                erlang:start_timer(1000, Pid, {});

        _ -> {}
    end.

state_server(Count, Requests) ->
    receive
        {request, Pid} ->
            state_server(Count, [Pid|Requests]);

        submit ->
            lists:map(fun(Pid) -> Pid ! term_to_str(Count) end, Requests),
            state_server(0, []);

        {timeout, _, _} ->
            erlang:start_timer(1000, self(), {}),
            lists:map(fun(Pid) -> Pid ! term_to_str(Count) end, Requests),
            state_server(Count+1, []);

        X ->
            io:put_chars("server got unkown message:"),
            io:write(X),
            io:put_chars("\n\n")
    end.
=== index.html =====================================
<html>
  <head> 
    <script type="text/javascript">

        function NewXmlHttpRequest() {
            var xmlhttp;

            // code for IE7+, Firefox, Chrome, Opera, Safari
            if (window.XMLHttpRequest) {
                xmlhttp = new XMLHttpRequest();
            }
            // code for IE6, IE5
            else {
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }

            xmlhttp.isReady = function() {
                // xmlhttp.status is defined once xmlhttp.readyState >= 2
                return this.readyState === 4 && this.status === 200;
            }
           
            return xmlhttp;   
        }

        function request() {
            xmlhttp = NewXmlHttpRequest();
            xmlhttp.onreadystatechange = function() {
                if (xmlhttp.isReady()) {
                    document.getElementById("counter").innerHTML =
                        xmlhttp.responseText;

                    request();
                }
            }
           
            // Send request off to server
            xmlhttp.open("GET", "yaws/request.yaws", true);
            xmlhttp.send();
        }

        function submit() {
            // Callback
            xmlhttp = NewXmlHttpRequest();
            xmlhttp.onreadystatechange = function() {}
           
            // Send request off to server
            xmlhttp.open("GET","yaws/submit.yaws", true);
            xmlhttp.send();
        }

    </script>
  </head>
 
  <body>
        <div id="counter">?</div>
        <input type="button" value="Reset" onclick="submit()">
        <div id="debug">_debug_</div>
        <script type="text/javascript">request()</script>
  </body>
</html>
=== yaws.conf ==============================
ebin_dir = "ebin/"

<server localhost>
    port = 8080
    listen = 127.0.0.1
    docroot = /home/mkd/www/prewix_bug
</server>

Michal




------------------------------------------------------------------------------
Forrester recently released a report on the Return on Investment (ROI) of
Google Apps. They found a 300% ROI, 38%-56% cost savings, and break-even
within 7 months.  Over 3 million businesses have gone Google with Google Apps:
an online email calendar, and document program that's accessible from your 
browser. Read the Forrester report: http://p.sf.net/sfu/googleapps-sfnew
_______________________________________________
Erlyaws-list mailing list
Erlyaws-list@...
https://lists.sourceforge.net/lists/listinfo/erlyaws-list
Steve Vinoski | 22 Dec 08:47 2010
Picon

Re: Multiple xml http request GET's

On Tue, Dec 21, 2010 at 8:41 PM, Michal D.
<michal.dobrogost@...> wrote:
>
> Thanks for taking an interest in my problem.   I created a toy version that
> will hopefully be easier to debug but it doesn't have exactly the same
> problem.  Same: sometimes 'reset' will hang the counter.  Different: real
> page always seems to hang, toy does not crash any processes.  Hopefully it
> will give you an idea of what's going on though.  I'll send the real code if
> still necessary.

I think the problem is in your JavaScript. You have the isReady() function:

>             xmlhttp.isReady = function() {
>                 // xmlhttp.status is defined once xmlhttp.readyState >= 2
>                 return this.readyState === 4 && this.status === 200;
>             }

which you use to call request() recursively, as shown below:

>         function request() {
>             xmlhttp = NewXmlHttpRequest();
>             xmlhttp.onreadystatechange = function() {
>                 if (xmlhttp.isReady()) {
>                     document.getElementById("counter").innerHTML =
>                         xmlhttp.responseText;
>
>                     request();
>                 }
>             }
>
>             // Send request off to server
>             xmlhttp.open("GET", "yaws/request.yaws", true);
>             xmlhttp.send();
>         }

but if xmlhttp.isReady() returns false, then the counter on the page
isn't updated and request() never gets called again, which in turn
means request.yaws is never retrieved again and things will appear to
hang.

--steve

------------------------------------------------------------------------------
Forrester recently released a report on the Return on Investment (ROI) of
Google Apps. They found a 300% ROI, 38%-56% cost savings, and break-even
within 7 months.  Over 3 million businesses have gone Google with Google Apps:
an online email calendar, and document program that's accessible from your 
browser. Read the Forrester report: http://p.sf.net/sfu/googleapps-sfnew
Nicolas Thauvin | 22 Dec 11:58 2010

yaws_session

Hi to the list !

  We are using Yaws and yaws_session to store some authentication tokens.  
The main drawback is that when we restart Yaws, (yeap.. it's a pain to do  
everything hot-upgradable), autenticated users become anonymous.

We are thinking about implementing a mnesia version of yaws_session, and  
why not share the module with the community. The idea would be to pass the  
backend engine as an argument when starting yaws_session_server (ets would  
still be the default, and a parameter could be added in yaws.conf).

But as Klacke said someday :
"If we involve mnesia or external ldap or what ever, it becomes quite more  
complex."

I agree with that, using mnesia would imply that the schema is already  
created as Yaws cannot guess the context in which it is executed. The best  
we can do is to create the table from yaws_session_server using the nodes  
appearing in the schema, assuming all the nodes are here...

What do you think ?  Would this kind of patch make this way into the Yaws  
release ?

-- Nicolas

------------------------------------------------------------------------------
Forrester recently released a report on the Return on Investment (ROI) of
Google Apps. They found a 300% ROI, 38%-56% cost savings, and break-even
within 7 months.  Over 3 million businesses have gone Google with Google Apps:
an online email calendar, and document program that's accessible from your 
browser. Read the Forrester report: http://p.sf.net/sfu/googleapps-sfnew
Steve Vinoski | 22 Dec 17:01 2010
Picon

Re: yaws_session

On Wed, Dec 22, 2010 at 5:58 AM, Nicolas Thauvin <nicolas@...> wrote:
> Hi to the list !
>
>  We are using Yaws and yaws_session to store some authentication tokens.
> The main drawback is that when we restart Yaws, (yeap.. it's a pain to do
> everything hot-upgradable), autenticated users become anonymous.
>
> We are thinking about implementing a mnesia version of yaws_session, and
> why not share the module with the community. The idea would be to pass the
> backend engine as an argument when starting yaws_session_server (ets would
> still be the default, and a parameter could be added in yaws.conf).
>
> But as Klacke said someday :
> "If we involve mnesia or external ldap or what ever, it becomes quite more
> complex."
>
> I agree with that, using mnesia would imply that the schema is already
> created as Yaws cannot guess the context in which it is executed. The best
> we can do is to create the table from yaws_session_server using the nodes
> appearing in the schema, assuming all the nodes are here...
>
> What do you think ?  Would this kind of patch make this way into the Yaws
> release ?

I can't speak for Klacke (who might be away on holiday at the moment,
not sure) but my opinion is that we would likely accept such a patch,
since as you say it seems like it could be useful for the community.
In addition to code changes, it would need doc changes to allow users
to find out how to set it up and use it, and including some tests for
the new feature would be great too. And as you said, we'd definitely
want to keep the ets default as it currently is.

--steve

------------------------------------------------------------------------------
Forrester recently released a report on the Return on Investment (ROI) of
Google Apps. They found a 300% ROI, 38%-56% cost savings, and break-even
within 7 months.  Over 3 million businesses have gone Google with Google Apps:
an online email calendar, and document program that's accessible from your 
browser. Read the Forrester report: http://p.sf.net/sfu/googleapps-sfnew
Michal D. | 22 Dec 17:48 2010
Picon

Re: Multiple xml http request GET's



I think the problem is in your JavaScript. You have the isReady() function:

>             xmlhttp.isReady = function() {
>                 // xmlhttp.status is defined once xmlhttp.readyState >= 2
>                 return this.readyState === 4 && this.status === 200;
>             }

which you use to call request() recursively, as shown below:

>         function request() {
>             xmlhttp = NewXmlHttpRequest();
>             xmlhttp.onreadystatechange = function() {
>                 if (xmlhttp.isReady()) {
>                     document.getElementById("counter").innerHTML =
>                         xmlhttp.responseText;
>
>                     request();
>                 }
>             }
>
>             // Send request off to server
>             xmlhttp.open("GET", "yaws/request.yaws", true);
>             xmlhttp.send();
>         }

but if xmlhttp.isReady() returns false, then the counter on the page
isn't updated and request() never gets called again, which in turn
means request.yaws is never retrieved again and things will appear to
hang.


Sure, that makes sense, but it seems to me that isReady() should eventually return true.  Its return status signifies that the server has completed transferring data to the client.  The callback itself is called multiple times as the transfer proceeds.  The server takes a request and holds on to it until it wants to send back data so the client really should eventually get a response back?
------------------------------------------------------------------------------
Forrester recently released a report on the Return on Investment (ROI) of
Google Apps. They found a 300% ROI, 38%-56% cost savings, and break-even
within 7 months.  Over 3 million businesses have gone Google with Google Apps:
an online email calendar, and document program that's accessible from your 
browser. Read the Forrester report: http://p.sf.net/sfu/googleapps-sfnew
_______________________________________________
Erlyaws-list mailing list
Erlyaws-list@...
https://lists.sourceforge.net/lists/listinfo/erlyaws-list
Steve Vinoski | 22 Dec 20:01 2010
Picon

Re: Multiple xml http request GET's

On Wed, Dec 22, 2010 at 11:48 AM, Michal D.
<michal.dobrogost@...> wrote:
>
> Sure, that makes sense, but it seems to me that isReady() should eventually
> return true.  Its return status signifies that the server has completed
> transferring data to the client.  The callback itself is called multiple
> times as the transfer proceeds.  The server takes a request and holds on to
> it until it wants to send back data so the client really should eventually
> get a response back?

I was running this in Firefox with Firebug enabled and watching the
JavaScript console, and you can definitely see that it gets to the
point where if you hit the reset button at just the right time, the
request loop stops. I don't know if it's because the submit() function
sets onreadystatechange to an empty function or what, but that's what
I see.

I also was running yaws interactively and was tracing the ebin
module's functions in the erlang shell, and I didn't see anything
going wrong with anything there.

--steve

------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and, 
should the need arise, upgrade to a full multi-node Oracle RAC database 
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
Claes Wikstrom | 23 Dec 09:36 2010

Re: yaws_session

On 12/22/2010 05:01 PM, Steve Vinoski wrote:

>
> I can't speak for Klacke (who might be away on holiday at the moment,
> not sure)

Nahh, working, a bit silent though. Lot's of good stuff happening.

> but my opinion is that we would likely accept such a patch,
> since as you say it seems like it could be useful for the community.

Indeed, having session data persistent is just fine. I don't think it'll
need any code _changes_ though. The session API is through
yaws_api:new_cookie_session and friends. This code speaks to yaws_session_server.

If you want persistent (mnesia or something else) sessions, all you need to
do is to not call the yaws_api functions in your application code but rather
call your own persistent session code.

Getting reusable mnesia dependent code into yaws in a good way is actually
hard. What about mnesia config options, table name, etc. I don't want that
into yaws, it's the wrong place.

Thus a reusable persistent session module should probably assume mnesia
is there already running fine. How do you propose to tell mnesia about the
new session table?

/klacke

------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and, 
should the need arise, upgrade to a full multi-node Oracle RAC database 
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
Nicolas Thauvin | 23 Dec 11:22 2010

Re: yaws_session

> If you want persistent (mnesia or something else) sessions, all you need  
> to do is to not call the yaws_api functions in your application code but  
> rather call your own persistent session code.

Well, I was about to code that in the first place, when I realized I would  
copy a lot of yaws_session_server logics and replace ets:insert by  
mnesia:write and so on... Make yaws_session_server work with different  
backends looked like the smarter option.
Leading us to the next question...

> Getting reusable mnesia dependent code into yaws in a good way is  
> actually hard. What about mnesia config options, table name, etc.

That's the tricky thing with mnesia, isn't it ;) ?

I think there is a documentation effort to make it possible. Proposition:
  * First, nodes have to be named and provided the -M option when started  
with appropriate mnesia session backend parameter
  * When nodes start the first time with the mnesia backend parameter, they  
drop an error report to signal the mnesia session system is not ready,  
reverting back to ets backend.
  * Once all the nodes are started in ETS mode, we could explain in the  
documentation:
   * how to create a schema if not already created (need to do  
application:stop(mnesia) first...)
   * how to issue a command to create the table on the running_db_nodes (or  
a subset of nodes) using for example yaws_session_server:init_mnesia(Nodes)
   * how to issue another command to switch to the new backend system  
without restarting Yaws
  * Upon next restart, if mnesia table exists and the mnesia session  
backend parameter is set, use mnesia as a backend

Not really plug and play, but at least the user has some control over the  
process (which is always good with mnesia...).
The other funny part is testing, maybe involving slaves and so on... a  
truly Erlang piece of joy!

> I don't want that into yaws, it's the wrong place.
I fully understand that. That's why I prefer to ask if such a patch is a  
good idea or if - as you said - we should keep it aside.

-- Nicolas

------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and, 
should the need arise, upgrade to a full multi-node Oracle RAC database 
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl

Gmane