[Tsung] Re: keepalive packets

Jason Tucker jasonwtucker at gmail.com
Fri May 18 18:24:33 CEST 2007


On 5/17/07, Jason Tucker <jasonwtucker at gmail.com> wrote:
>
> I'm seeing an odd problem that is very hard to replicate, but I think it
> may have to do with keepalive messages being sent by the XMPP server...
>
> I'm running a transaction that expects a response from the server in order
> to populate a dynvar. I suspect that in rare cases, under high load, it is
> possible for a server keepalive message to beat the expected response
> message back to the client. In this case, the client would try to parse the
> keepalive message and fail to populate the dynvar, no? Is this a possiblity?
>
>
> And if so, is there a way to modify the client code to basically ignore
> the keepalives? BTW, the keepalive message is essentially just a "space"
> character sent across the stream. So, if my suspicions are correct, what we
> want to do is modify the client so that it will not pass messages less than
> 2 bytes in size to ts_search.
>
> Thoughts?



I *think* I found a fix for this condition in ts_client.erl. Here is the
original code:

%% local ack, set ack_done to true
handle_data_msg(Data, State=#state_rcv{request=Req, maxcount= MaxCount}) ->
	ts_mon:rcvmes({State#state_rcv.dump, self(), Data}),
    NewBuffer= set_new_buffer(Req, State#state_rcv.buffer, Data),
	DataSize = size(Data),
    {PageTimeStamp, DynVars} = update_stats(State#state_rcv{datasize=DataSize,
                                                            buffer=NewBuffer}),
    NewCount = ts_search:match(Req#ts_request.match, NewBuffer,
{State#state_rcv.count,MaxCount}),
    NewDynData = concat_dynvars(DynVars, State#state_rcv.dyndata),
    {State#state_rcv{ack_done = true, buffer= NewBuffer, dyndata = NewDynData,
                     page_timestamp= PageTimeStamp, count=NewCount},[]}.


And here is the change I made - I just added an if statement which checks
size(Data) :

%% local ack, set ack_done to true
handle_data_msg(Data, State=#state_rcv{request=Req, maxcount= MaxCount}) ->
	ts_mon:rcvmes({State#state_rcv.dump, self(), Data}),
    NewBuffer= set_new_buffer(Req, State#state_rcv.buffer, Data),
	DataSize = size(Data),
    {PageTimeStamp, DynVars} = update_stats(State#state_rcv{datasize=DataSize,
                                                            buffer=NewBuffer}),
    NewCount = ts_search:match(Req#ts_request.match, NewBuffer,
{State#state_rcv.count,MaxCount}),
    NewDynData = concat_dynvars(DynVars, State#state_rcv.dyndata),

    if
        size(Data) < 2 ->
            %% our dyndata must in a packet larger than 1 byte, set
ack_done to false
            {State#state_rcv{ack_done = false, buffer= NewBuffer,
dyndata = NewDynData,
            page_timestamp= PageTimeStamp, count=NewCount},[]};
        true ->
            %% this packet is a candidate to contain dyndata, set
ack_done to true
            {State#state_rcv{ack_done = true, buffer= NewBuffer,
dyndata = NewDynData,
            page_timestamp= PageTimeStamp, count=NewCount},[]}
    end.


I'm still testing this, but so far, it seems to work. If the client is
expecting a server response to populate a dynvar, and a keepalive packet
comes in first, the client will just keep waiting for a properly sized
packet to fulfill the local_ack requirement.

__Jason
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.process-one.net/pipermail/tsung-users/attachments/20070518/e6d9764c/attachment.html


More information about the Tsung-users mailing list