Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Problem with llHttpRequest when loading settings notecard

Bones Outlander
Registered User
Join date: 16 Jan 2008
Posts: 30
01-24-2008 06:03
I'm having a problem that once again I'm sure there is an easy solution for :)

I execute the following script to load in the settings in my notecard.

One of the lines is Avatar=<name>,<UUID>

The thing is I want to do a lookup if only the name is provided and no key.

Now I thought that would be easy, but it isn't working.... the llHttpRequest result isn't returned correctly if there are more than one Avatar= lines with only a name.. I assume because the code continues to execute while the httpRequest is being processed.

What should I do to correct this?

Thanks.


CODE
(Note: some of the variables referenced in this script are set outside this script, but they are set and are correct)
---------------------------

state readNotecard
{
state_entry()
{

llOwnerSay("Loading Configuration Notecard";);
llSetText("Loading",<1,1,1>, 1.0);
if (llGetInventoryType(sCONFIG_CARD) == INVENTORY_NOTECARD)
{
iLineCounter = 0;
lAvi_name=[];
lAvi_keyid=[];
lAvi_status=[];
kDataRequestID = llGetNotecardLine( sCONFIG_CARD, iLineCounter );
}
else
{
llOwnerSay("Configuration notecard missing, voice control only.";);
iCard_loaded = FALSE;
state Running;
}
}

http_response(key kId, integer iStatus, list lMeta, string sBody)
{
if ( kId != kReqid )
{
return;
}
if ( iStatus == 499 )
{
llOwnerSay("name2key request timed out";);
}
else if ( iStatus != 200 )
{
llOwnerSay("the internet exploded!!";);
}
else if ( (key)sBody == NULL_KEY )
{
llOwnerSay("No key found for " + sAviName);
}
else
{
lAvi_keyid += [sBody];
return;

}
}

dataserver(key kQueryid, string sData)
{
if (kDataRequestID)
{
if (sData != EOF)
{
if( StringLeftICompare("PollInterval=", sData ) ){
iPollInterval = (integer)GetValue( sData );
llOwnerSay("Poll Interval set to " + (string)iPollInterval);
}
else if( StringLeftICompare( "Avatar=", sData ) ){
list lTemp = llParseString2List(sData,["Avatar","=",","],[]);
string sAviName=llStringTrim(llList2String(lTemp,0),STRING_TRIM);
lAvi_name += [sAviName];
sKeyID=llStringTrim(llList2String(lTemp,1),STRING_TRIM);
if (sKeyID=="";){
kReqid = llHTTPRequest( sURL + "?terse=1&name="+llEscapeURL(sAviName), [], "" );
}
else {
lAvi_keyid += [sKeyID];
}
lAvi_status += ["OFFLINE"];
}

iLineCounter +=1;
kDataRequestID = llGetNotecardLine(sCONFIG_CARD, iLineCounter);
}
else
{
llOwnerSay("Loading Complete, " + (string)llGetListLength(lAvi_name) + " avatars loaded.";);
llSetText("Config Loaded",<1,1,1>, 1.0);
iCard_loaded = TRUE;
state Running;
}
}
}

}
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
01-24-2008 09:03
EDIT: Nevermind. See my next post.

The entire contents of the HTTP response get returned in the body, not just one line. If your response is multi-line and you want to process each line in turn, you'll have to break up the body of the response on newline characters with something like:

CODE

list lines = llParseList2String(body, [ "\n" ], []);
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
01-24-2008 09:09
Oh. Oops. Now I see what you are getting at. Yeah, you have a race condition happening. The behavior of the script will depend on which is faster: the HTTP request, or the read of the next notecard line. You are probably going to have to either keep track of multiple requests at once with lists (this can become memory intensive), or set your logic up to read the next notecard line only after the HTTP response has been received (and you'll need to figure out what to do on timeout or other error).
Bones Outlander
Registered User
Join date: 16 Jan 2008
Posts: 30
01-24-2008 13:11
Thanks Hewee,

I think I;'d prefer to wait for the llHttpRequest to process before moving on, but aren't quite sure how to do this.

I assume I need to loop on some conditional in here
if (sKeyID=="";){
kReqid = llHTTPRequest( sURL + "?terse=1&name="+llEscapeURL(sAviName), [], "" );
// LOOP AND WAIT FOR A RESPONSE ????
}
else {
lAvi_keyid += [sKeyID];
}



I tried a few things but couldn't get it working.

Can you give me an example please?

Thanks
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
01-24-2008 13:25
In the 'http_response' handler, instead of returning after you successfully add a key, I suggest making the request for the next notecard line (don't do this from the 'dataserver' handler in cases where you make the HTTP request). EDIT: To be more clear, don't simply return after ANY path through this code except the first 'if' that represents the case that the response was not to your request.

This way you can view the 'http_request' body as a natural extension of your processing of a notecard line. When it is done, that is when you request the next line. You'll still stop requesting lines when you get EOF in the dataserver event.
Bones Outlander
Registered User
Join date: 16 Jan 2008
Posts: 30
01-24-2008 13:55
From: Hewee Zetkin
In the 'http_response' handler, instead of returning after you successfully add a key, I suggest making the request for the next notecard line (don't do this from the 'dataserver' handler in cases where you make the HTTP request). EDIT: To be more clear, don't simply return after ANY path through this code except the first 'if' that represents the case that the response was not to your request.

This way you can view the 'http_request' body as a natural extension of your processing of a notecard line. When it is done, that is when you request the next line. You'll still stop requesting lines when you get EOF in the dataserver event.



Sorry, don't fully understand,

Are you saying add the
iLineCounter +=1;
kDataRequestID = llGetNotecardLine(sCONFIG_CARD, iLineCounter);

into the http_response handler after all the if statements

And then only execute the other notecard line request in the dataserver section if my line IS NOT "Avatar=" ?

Cheers
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
01-24-2008 15:03
Yep. I think that should do it.