|
Feline Slade
Hatstand 2.0™
Join date: 19 May 2007
Posts: 201
|
11-21-2007 11:19
I've done some searches and haven't found any good explanation to help me with this. If there already was, please point me to the thread.
I currently have a set of scripts that in a prim that makes data available to each other via llMessageLinked and link_message. The problem I'm having is that one of them does a llRequestAgentData request. It appears that the dataserver in that script is firing each time a llMessageLinked message is sent by any of the prims. I had initially thought that only link_message was triggered by this kind of message, so I was surprised to see it. This means that instead of firing a few times a minute, as expected, it's firing 100+ times a minute. The script is currently generating a stack heap error after a while, and I suspect that this is the culprit.
Do I need to put this script in a separate prim and have the data sent out of the original prim in order to eliminate this? Or is there something I'm missing here?
Thanks in advance for any assistance!
|
|
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
|
11-21-2007 13:09
Slightly tricky without seeing the script but...
I'm guessing you need to establish some kind of 'request identifier' when broadcasting using the llMessageLinked functions. For example you might use the 'integer num' to identify the type of request. So, 1001 could mean: I'm broadcasting some agent data and I want to know if they're online.
llMessageLinked(LINK_THIS, 1001, "", kAgentId)
And 2001 could indicate a reply to 1001:
llMessageLinked(LINK_THIS, 2001, TRUE/FALSE, kAgentId)
The individual scripts can then use the integer identifier to decide if the message they receive is something they need to handle. So, in your case, your 'dataserver script' would only respond if it receives 1001 in its link_message Event Handler and it would ignore all other requests.
I'm guessing that the current situation is that it is responding to all request because it has no away of filtering out what to it is just noise.
Also bear in mind that the dataserver event is raised in ALL scripts in the prim regardless of which script made a request. If this is an issue it is important to filter the dataserver events according to the key assigned to the request:
kQueryId = llRequestAgentData(kAgentId, DATA_ONLINE)
dataserver(key queryid, string data) { if (queryid == kQueryId) { : etc.
Basically, I think you just need to take care to make sure that the scripts only respond to what is relevant to them when you may not be able to avoid having them receive events intended for each other.
|
|
Feline Slade
Hatstand 2.0™
Join date: 19 May 2007
Posts: 201
|
11-22-2007 07:47
Thanks for your response. That's what I'm doing. It isn't that the dataserver is responding to everything. It's not. But I'm wondering if it being fired so often is what is eventually causing a stack heap collision. I'm pasting the code below. It works beautifully for about 4 hours before crashing.... ///// // Receives list of keys from Notecard Reader and Key Lookup script // Determines that the incoming message is message 40 // Looks up status of avatar using received key // Concatonates avatar status onto a pipe-delimited string // Determines when length of values in the string is equal to length of original string of keys // When list is complete, sends list of avatar statuses via llMessageLinked as message 150 // Looks up and sends unix time (as string) via llMessageLinked as message 180 // Clears avatar status string for next time a list of keys is received. //
// Global Variables
key onlineStatusRequest; key placeholder;
string incomingText; string incomingKeyID; string avatarStatus; string avatarStatuses = "";
integer avatarNumber = 1; integer incomingNumber = 0; integer incomingListLength = 0; integer originalListLength = 0; integer loopCounter = 0; integer unixTime;
list incomingList; list keyList;
statusCompile() { //check to see if the list of avatar statuses is now full length //first increment the loop counter to account for this returned data loopCounter = loopCounter + 1; if((string)loopCounter == (string)originalListLength ) { llMessageLinked(LINK_SET, 150, avatarStatuses, placeholder); avatarStatuses = ""; //Get the unix time unixTime = llGetUnixTime(); llMessageLinked(LINK_SET, 180, (string)unixTime, placeholder); //Reset the script to clear the memory llResetScript(); }else{ keyList = llDeleteSubList(keyList, 0, 0); onlineStatusRequest = llRequestAgentData(llList2String(keyList, 0), DATA_ONLINE); } }
default { link_message(integer Sender, integer Number, string Text, key ID) { //When this prim receives a message, identify which avatar and whether online. incomingText = Text; incomingNumber = Number; incomingKeyID = ID; incomingList = llParseString2List(incomingText,["|"],[]); incomingListLength = llGetListLength(llParseString2List(incomingText,["|"],[])); originalListLength = incomingListLength;
// if string of avatar keys is received if (incomingNumber == 340 ) { keyList = incomingList;
onlineStatusRequest = llRequestAgentData(llList2String(keyList, 0), DATA_ONLINE); } }
dataserver(key queryid, string data) { // this is what SL returns to us when we call llRequestAgentData() if (queryid == onlineStatusRequest) // check if it’s the correct request { if (data == "1") // online status is just 0 or 1 { //avatarStatus = "Online"; avatarStatuses = (avatarStatuses = "") + avatarStatuses + "Online" + "|"; //if status is full length, send as msg 150, else look up next avatar key statusCompile(); } else { //avatarStatus = "Offline"; avatarStatuses = (avatarStatuses = "") + avatarStatuses + "Offline" + "|"; //if status is full length, send as msg 150, else look up next avatar key statusCompile(); } } } }
Maybe I'm missing some necessary script housecleaning and can't find it? Any input is appreciated.
|
|
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
|
11-22-2007 12:18
I think llResetScript is as clean as it's going to get! In any event your script must be running out of memory, and as I can see no obvious leak I can only assume that the combined sizes of incomingList and keyList are doing this. I don't see any reason to have both lists. You pass off the data from incomingList to keylist never to reference incomingList again. I think you could remove the line: keyList = incomingList, and just proceed with incomingList. If these lists can be big then that may solve the problem. You're also have a similar duplication with the strings Text and incomingText (and a number of other variables but they're all just small-fry). I think you just need to take care how you handle big lists and strings. I also suspect someone could come up with a more cunning (aka memory efficient) way of doing: incomingList = llParseString2List(incomingText,["|"],[]); ...such that incomingText gets destroyed as it is parsed into incomingList. We need an expert in Perverse Coding. 
|
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
11-22-2007 12:26
incomingList = (incomingList = []) + incomingList + llParseString2List(incomingText,["|"],[]); http://www.cheesefactory.us/lslwm/list.htm
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime. From: someone I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
|
|
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
|
11-22-2007 13:22
I think in this case we're not appending to the list... the list is already empty. This is a once off parsing of incomingText... I was hoping for something more like: incomingList = [incomingText] + llParseString2List(incomingText,["|"],[]); ...but I'm not exactly sure how the destroy as you go thing works, or in what order it should be done. I'm too intuitive. 
|