Jump to content

llGetNotecardLineSync()


Cain Maven
 Share

You are about to reply to a thread that has been inactive for 70 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

11 hours ago, Wulfie Reanimator said:

Noticed really annoying (but consistent) behavior I never knew about.

If the last line of a notecard contains text but no newline, trying to read that line will return EOF instead of the text.

This happens with Sync/Async and applies even to notecards that only contain one line of text, but no newline. The line cannot be read because the result is EOF. I'm sure someone has to have filed a jira about it, but what's the current status?

That is a bug specific to Gingerbread server versions. I'll file it on the crappy canny system and bring it up tomorrow at the server UG. Thanks.

https://feedback.secondlife.com/scripting-bugs/p/reading-last-notecard-line-text-returns-eof

Sadly, this will most likely push access on agni back a week. 😐

Edited by Lucia Nightfire
  • Thanks 2
Link to comment
Share on other sites

12 hours ago, Qie Niangao said:

if it needs a random line "occasionally" it may call the sync version in hopes it gets lucky on the first try.

i think a get lucky ISAM strategy can be viable under light/moderate server load. A safe method can be something like

// data handler function
handleData(string data)
{
   if (data != EOF)
   {
 
      ... do something with this notecardLine of data ...

   }
}


// a prior call to set up the cache
llGetNumberOfNotecardLines();



// under light/moderate load then more times than not this 
// will result in something other than NAK
string data = llGetNotecardLineSync(notecardName, notecardLine);
if (data != NAK)
    handleData(data);
else
    notecardQuery = llGetNotecardLine(notecardName, notecardLine);



dataserver(key query, string data)
{
   if (query == notecardQuery)
	handleData(data);
}

 

  • Like 1
Link to comment
Share on other sites

5 hours ago, elleevelyn said:

i think a get lucky ISAM strategy can be viable under light/moderate server load. A safe method can be something like

I was trying not to call a user-defined function for each line read, but if there are many places in the script where a line of notecard data gets used it's not practical to inline the code for reading and NAK-recovery at each of those places.

Another design question is whether it's worth processing the data fetched in the async NAK-recovery call, rather than fetching it again synchronously and ignoring the dataserver event. If the timing of recovery is too unpredictable, it would be worth waiting for that event, and then with the data already at hand may as well use it. But my hunch is the (re-)caching will almost always be practically instantaneous, so I'm currently favoring using the async call only to make ready a sync call. So that'll be an empirical question, once we get this function on the main grid.

If I remember to attend today's user group, I might ask Ryder's take on that, and on basic behavior of the cache (does it flush at region restart? do repeated reads count as "uses" to deter LRU cache aging or something? —especially sync reads?).

Also, I've been guessing that llGetNumberOfNotecardLines() is slightly less work than fetching-up a string into the event with llGetNotecardLine(), so if I'm going to ignore the dataserver event anyway, I've been using the -Number function. It probably doesn't matter much, but maybe it doesn't matter at all. One could try measuring it, but with that 100msec delay per call I'm dubious of results.

  • Like 2
Link to comment
Share on other sites

1 hour ago, Qie Niangao said:

I was trying not to call a user-defined function for each line read, but if there are many places in the script where a line of notecard data gets used it's not practical to inline the code for reading and NAK-recovery at each of those places.

Another design question is whether it's worth processing the data fetched in the async NAK-recovery call, rather than fetching it again synchronously and ignoring the dataserver event. If the timing of recovery is too unpredictable, it would be worth waiting for that event, and then with the data already at hand may as well use it. But my hunch is the (re-)caching will almost always be practically instantaneous, so I'm currently favoring using the async call only to make ready a sync call. So that'll be an empirical question, once we get this function on the main grid.

...

Also, I've been guessing that llGetNumberOfNotecardLines() is slightly less work than fetching-up a string into the event with llGetNotecardLine(), so if I'm going to ignore the dataserver event anyway, I've been using the -Number function. It probably doesn't matter much, but maybe it doesn't matter at all. One could try measuring it, but with that 100msec delay per call I'm dubious of results.

yes if we going to be reading notecard in more than one place then a user-defined function, if not then inline it

in either case then I think we left with something like this

string notecardISAM(string notecard, integer line)
{
    llGetNumberOfNotecardLines(notecard);
    integer retry = -3;  // retry 3 times
    string data;
    do
    {   /* alternatively
           llGetNumberOfNotecardLines(notecard);
           could go here, and we thrash it upto retry times
        */
        data = llGetNotecardLineSync(notecard, line);
   	if (data == NAK)
   	{  // non-eventblocking pause before we retry
       	   float pause = llGetTime() + 0.1;
           while (llGetTime() < pause);
        }
    } while (retry++ && data == NAK);
    return data;
}

it can still return NAK but this would be no different to a standard ISAM system in how we then deal with it

we could also make it smarter where we monitor cache performance. Adjusting retry and pause in response

Edited by elleevelyn
more info
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

just a wish

i wish there to be a way to check whether the notecard is cached. Something like integer yes = llIsNotecardCached(notecardName) and when this function is called the notecard in cache is moved to the front so is last out of the cache

thank you Any Linden who might read this :)

 

Edited by elleevelyn
Link to comment
Share on other sites

34 minutes ago, Wulfie Reanimator said:

This blocks events just the same as any other loop/sleep.

you right about this, i had a look. I should spend more time learning about how LSL actual works rather than just assume it works like other interrupt event driven languages that I am used too

Link to comment
Share on other sites

2 hours ago, elleevelyn said:

I should spend more time learning about how LSL actual works rather than just assume it works like other interrupt event driven languages that I am used too

single threaded, with a fifo queue that holds 64? events. Ergo, nothing can happen 'at the same time' in a single script.

  • Thanks 2
Link to comment
Share on other sites

3 hours ago, Wulfie Reanimator said:

This blocks events just the same as any other loop/sleep.

Event functions cannot "fire", but the events will still get "queued". (Users can still click the object for example, resulting in a queued touch_start() event.)

From that perspective, are they truly being "blocked"?

Not trying to quibble, really! 

When you remove a listener via llListenRemove(), or inactivate it via llListenControl(), would we say it is "blocking" events? Or not, since the event will never occur?

I guess @Quistess Alpha's reply above explains it in a way that covers my non-quibble!

Link to comment
Share on other sites

-- irrelevant tangent --

Certain high-frequency events like touch() and control() jump-queue and replace their last instance such that there is only ever one event of the type in the queue (preventing it from overflowing too easily). consider

default
{   touch_start(integer n)
    {   llSleep(1.0); }
    touch(integer n)
    {   llOwnerSay((string)llGetTime()); }
} // touching this object for less than 1 second produces only 1 line of output.

 

21 minutes ago, Love Zhaoying said:

When you remove a listener via llListenRemove(), or inactivate it via llListenControl(), would we say it is "blocking" events? Or not, since the event will never occur?

That's a bit of a semantic question, but I'd reserve the term 'blocking' only for scenarios where an event sleeps or loops for an unordinarily long time. It's the difference between closing your eyes and turning off your monitor. Maybe if you want to be pedantically more correct, you could say llListenControl "masks" the event?

Edited by Quistess Alpha
  • Thanks 1
Link to comment
Share on other sites

12 minutes ago, Love Zhaoying said:

Event functions cannot "fire", but the events will still get "queued". (Users can still click the object for example, resulting in a queued touch_start() event.)

From that perspective, are they truly being "blocked"?

Not trying to quibble, really! 

When you remove a listener via llListenRemove(), or inactivate it via llListenControl(), would we say it is "blocking" events? Or not, since the event will never occur?

I guess @Quistess Alpha's reply above explains it in a way that covers my non-quibble!

The original comment I responded to was implying that events could come in and interrupt the loop, which we all now know is not the case.

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

llGetNotecardLineSync discussion at the Simulator User group first cleared up some confusion about the fact it returns EOF, then… well, here's a lightly edited hunk of transcript:

Quote

[2024/01/30 12:18]  Rider Linden: BUT! Best practice is to get the number of lines prior to doing any sync reading.  That will ensure that the card is in the cache.
[2024/01/30 12:19]  Vale (thunder.rahja): Time to fork AVsitter
[2024/01/30 12:19]  Lucy daughter of the Devil (lucia.nightfire): I rec getting nc line count first as well, you're doing two things, caching and getting line count
[2024/01/30 12:19]  Lucy daughter of the Devil (lucia.nightfire): idt I've had to rely on EOF in over a decade
[2024/01/30 12:19]  Rider Linden: Two birds with one call.  Yes.
[2024/01/30 12:19]  Jenna Felton: (maybe the page was updated, because now i see the lune where it stands that EOF is sent) I was talking to someone and we deixussed how cool the function is, but we not noriced that line and wndeered how to avoid the dataserver event entirelly, because less events, less memory :)
[2024/01/30 12:19]  Legacy.Name (wulfie.reanimator): About the notecard caching system... can you give details on what things factor into a notecard's lifetime? I noticed that my notecard was cached for several hours.
[2024/01/30 12:20]  Lucy daughter of the Devil (lucia.nightfire): probably why Wulf found the EOF bug before me, heh
[2024/01/30 12:20]  Rider Linden: Except for now that I broke it... (that will be fixed before it rolls.)
[2024/01/30 12:20]  Hana (treesbreeze): ฅ/ᐠ。ᆽ。ᐟ \
[2024/01/30 12:20]  Lucy daughter of the Devil (lucia.nightfire): nc cache "should" 24 hours after the last usage of all 3 nc functions
[2024/01/30 12:20]  Vale (thunder.rahja): It might be best practice to get the number of notecard lines before every series of sync reading, or if random access is needed, port it into linkset data.
[2024/01/30 12:20]  Lucy daughter of the Devil (lucia.nightfire): *of any
[2024/01/30 12:21]  Lucy daughter of the Devil (lucia.nightfire): I haven't done volatile cache testing yet, though
[2024/01/30 12:21]  Vale (thunder.rahja): The only thing I'm getting from the wiki article is "don't rely on caching"
[2024/01/30 12:21]  Rider Linden: Leviathan actually spotted a bug where cards might be kept for less time than necessary.  I'll get a fix for that into Hearts & Flowers. It didn't matter before because if the card got swapped out it would just go fetch it again.
[2024/01/30 12:22]  Henri Beauchamp: How can you ensure a notecard will get cached before using llGetNotecardLineSync() ?
[2024/01/30 12:22]  Vale (thunder.rahja): Get the number of lines first, Henri.
[2024/01/30 12:22]  Rider Linden: By getting the number of lines.
[2024/01/30 12:22]  Lucy daughter of the Devil (lucia.nightfire): calling either get nc line or get num nc lines
[2024/01/30 12:22]  Qie Niangao: Is it possible to guess how variable the time needed to (re-)cache a notecard, in non-exceptional cases? On aditi it seems to always be ready after the 100msec delay for an asynch call, but maybe just lucky?
[2024/01/30 12:23]  Lucy daughter of the Devil (lucia.nightfire): Qie, depends on bytes
[2024/01/30 12:23]  Lucy daughter of the Devil (lucia.nightfire): 64 KiB "could" take up to 10s
[2024/01/30 12:23]  Lucy daughter of the Devil (lucia.nightfire): don't ask me why though
[2024/01/30 12:23]  Qie Niangao: to cache a notecard? wow
[2024/01/30 12:23]  Lucy daughter of the Devil (lucia.nightfire): yes
[2024/01/30 12:23]  Vale (thunder.rahja): One issue I foresee is if a script is sync reading a notecard that a user is editing. Saving replaces the notecard and would require the new notecard be cached before sync reading could continue.
[2024/01/30 12:24]  Rider Linden: When I say "don't really on caching" I mean that don't read a line from a notecard sync and expect it to still be there 10 minutes later.  (or even 5)  The cache time depends a great deal on the number of scripts that are accessing different notecards.
[2024/01/30 12:24]  Lucy daughter of the Devil (lucia.nightfire): @Thunder, apps should be looking for inv change
[2024/01/30 12:24]  Rider Linden: Only if you want to drive yourself insane Qie.
[2024/01/30 12:24]  Lucy daughter of the Devil (lucia.nightfire): if the app relies on remote nv reading, then there has to be some ext comm
[2024/01/30 12:24]  Qie Niangao: yeah, that's good to know. (not what I expected, but good to know)
[2024/01/30 12:24]  Vale (thunder.rahja): I'm saying that replacing llGetNotecardLine with llGetNotecardLineSync is not a simple swap, Lucy.
[2024/01/30 12:25]  Lucy daughter of the Devil (lucia.nightfire): it depends on how you structure your code to deal with errors/failures
[2024/01/30 12:25]  Rider Linden: I would VERY strongly advise against trying to pick up reading where you left off in the event of an inventory change Vale. You've no guarantee what part of the card has changed.
[2024/01/30 12:26]  Lucy daughter of the Devil (lucia.nightfire): and by errors I mean intermittently, even while in a loop that doesn't exit an event
[2024/01/30 12:26]  Vale (thunder.rahja): /me coughs
[2024/01/30 12:26]  Legacy.Name (wulfie.reanimator): On a scale of 1 to 10, how safe is it to assume that you can read a full notecard on first try after caching? Some people think that a notecard could get uncached mid-loop, for example.
[2024/01/30 12:27]  Rider Linden: The script may yield to other scripts or simulator processes from a loop.  Even if it hasn't exited an event yet Lucy.
[2024/01/30 12:27]  Amalia Kalio (amalia.irata): Maybe an llGetNotecardHash or llGetInvetoryItemHash or something to validate it's the same? (Assuming the asset UUID didn't change.)
[2024/01/30 12:27]  Leviathan Linden: I would rate it at 9.  You still need to handle the failure case.
[2024/01/30 12:27]  Lucy daughter of the Devil (lucia.nightfire): sometimes in some of my long read apps, I even have to check for external changes, such as region changes/restarts or even if the app was taken/returned into user inv during a long read session
[2024/01/30 12:27]  Vale (thunder.rahja): The UUID always changes when a notecard's contents change, Amalia.
[2024/01/30 12:27]  Legacy.Name (wulfie.reanimator): Thanks Leviathan.
[2024/01/30 12:27]  Qie Niangao: oh, and that reminds me: is it very likely that notecards will be uncached by a server restart?
[2024/01/30 12:27]  Jenna Felton: There is no wiki page for NAK
[2024/01/30 12:27]  Amalia Kalio (amalia.irata): Perfecrt
[2024/01/30 12:27]  Amalia Kalio (amalia.irata): Perfect, even.
[2024/01/30 12:27]  Rider Linden: I'd give it an 8 or a 9 for safety Wulfie.
[2024/01/30 12:27]  Lucy daughter of the Devil (lucia.nightfire): it's annoying and consumes bytecode, but it does bulletproof a script
[2024/01/30 12:28]  Rider Linden: You should probably still check for NAK in your loop.
[2024/01/30 12:28]  Leviathan Linden: The cache does NOT survive simulator restart.
[2024/01/30 12:28]  dantia Gothly: It would be nice to be able to know what contents changed in the object.
[2024/01/30 12:28]  Qie Niangao: thanks Leviathan. That's what I expected.
[2024/01/30 12:28]  Rider Linden: Vale, yes.  That is true, a change to the notecard will change it's UUID.
[2024/01/30 12:28]  dantia Gothly: a function or event to tell you x file changed in the contents would be nice.
[2024/01/30 12:29]  Lucy daughter of the Devil (lucia.nightfire): IIRC, someone filed a req for such a function
[2024/01/30 12:29]  Jenna Felton: I think i would try to read the notecard via llGetNotecardLineSync and when i get NAK, then i recache it by requesting the notecard lines, maybe it will even work withoug having dataserver event.  otherwise keep reading. will try this plan when i get to it :)
[2024/01/30 12:29]  dantia Gothly: I requested an event for it
[2024/01/30 12:30]  Amalia Kalio (amalia.irata): llGetInventoryKey can serve as a checksum if you know the asset name
[2024/01/30 12:30]  Rider Linden: I seem to recall that feature request... but I'm drawing a blank on the specifics.
[2024/01/30 12:30]  Amalia Kalio (amalia.irata): Store the last known ID, check if it's the same
[2024/01/30 12:30]  dantia Gothly: it was in jira
[2024/01/30 12:30]  Vale (thunder.rahja): Caveat: llGetInventoryKey only works on items the owner has full permissions to.
[2024/01/30 12:30]  Legacy.Name (wulfie.reanimator): And likewise the previous UUID is still a valid asset and can be read practically forever.
[2024/01/30 12:31]  Legacy.Name (wulfie.reanimator): (I was scrolled up a bit, oops.)
[2024/01/30 12:31]  Rider Linden: I'll look it up after the meeting.  My JIRA foo has become obsolete.

What I take away from all this is:

  • we need to handle NAKs every time (no surprise)
  • it may not be worth synchronous retries outside the dataserver() handler, especially for large notecards
  • recent success correlates (but imperfectly) with continuing success: if it's cached in one frame, it's (only) probably still cached in the next
  • the more notecards a region reads, the sooner one will expire from cache after use
  • if the region restarts and you're likely to read a specific notecard soon, maybe pre-heat the cache with an async read (ignoring the results) to improve hit rate on the next sync read
  • Thanks 3
Link to comment
Share on other sites

7 hours ago, Quistess Alpha said:

single threaded, with a fifo queue that holds 64? events. Ergo, nothing can happen 'at the same time' in a single script.

yes. I had a quick play with llSetTimerEvent just to proof it using llSleep vs "pause". The outcome is identical

Link to comment
Share on other sites

7 hours ago, Wulfie Reanimator said:

The original comment I responded to was implying that events could come in and interrupt the loop, which we all now know is not the case.

yes this is true. Thanks for pointing this out to me. Going forward if I do need to pause a script then I be using llSleep from now on

Link to comment
Share on other sites

22 minutes ago, Qie Niangao said:

llGetNotecardLineSync discussion at the Simulator User group first cleared up some confusion about the fact it returns EOF, then… well, here's a lightly edited hunk of transcript:

What I take away from all this is:

  • we need to handle NAKs every time (no surprise)
  • it may not be worth synchronous retries outside the dataserver() handler, especially for large notecards
  • recent success correlates (but imperfectly) with continuing success: if it's cached in one frame, it's (only) probably still cached in the next
  • the more notecards a region reads, the sooner one will expire from cache after use
  • if the region restarts and you're likely to read a specific notecard soon, maybe pre-heat the cache with an async read (ignoring the results) to improve hit rate on the next sync read

I thought by your EOF reference you were meaning the "new" bug where the last line returns EOF if there's no extra blank line / CRLF at the end..? (I did not see that in the transcript..)

Thanks!

Link to comment
Share on other sites

1 hour ago, Love Zhaoying said:

I thought by your EOF reference you were meaning the "new" bug where the last line returns EOF if there's no extra blank line / CRLF at the end..? (I did not see that in the transcript..)

Thanks!

Yeah, that part is a bit truncated, but it's referred to in the quotes:
[2024/01/30 12:20]  Lucy daughter of the Devil (lucia.nightfire): probably why Wulf found the EOF bug before me, heh
[2024/01/30 12:20]  Rider Linden: Except for now that I broke it... (that will be fixed before it rolls.)

The EOF-related confusion I mentioned, however, was whether the Sync version ever returned EOF at all; there may have been some version of the wiki page that omitted that.

  • Thanks 1
Link to comment
Share on other sites

26 minutes ago, Qie Niangao said:

Yeah, that part is a bit truncated, but it's referred to in the quotes:
[2024/01/30 12:20]  Lucy daughter of the Devil (lucia.nightfire): probably why Wulf found the EOF bug before me, heh
[2024/01/30 12:20]  Rider Linden: Except for now that I broke it... (that will be fixed before it rolls.)

The EOF-related confusion I mentioned, however, was whether the Sync version ever returned EOF at all; there may have been some version of the wiki page that omitted that.

I hope the sync version does return EOF, or we'll always have to check # lines. And my plan to read async if sync failed wouldn't work if I needed to requery # lines instead of depending on EOF!!

Link to comment
Share on other sites

1 hour ago, Love Zhaoying said:

I hope the sync version does return EOF, or we'll always have to check # lines. And my plan to read async if sync failed wouldn't work if I needed to requery # lines instead of depending on EOF!!

As per the test scripts in this thread, including mine, yes it returns EOF.

I don't know where this misconception that you need tthe line count comes from all of a sudden, you just need to call one of the async functions to cache the notecard, you don't need to handle the async event or do anything with what's returned.

I'm certainly going to (ab)use that style; adding the -Sync version will be a nice speed boost drop-in to existing dataserver-event based notecard reading, but having to service an async event to be able to use a sync function sounds like it's not very synchronous at all... and sometimes you just might want to get the data right there, right now (even if it takes a retry or two to get a proper return value). If the asset server is so knackered it can't fulfill that, I'm pretty sure there are more pressing issues and trying to do old async reading wouldn't be working great either.

  • Thanks 1
Link to comment
Share on other sites

5 hours ago, Qie Niangao said:

What I take away from all this is:

  • we need to handle NAKs every time (no surprise)
  • it may not be worth synchronous retries outside the dataserver() handler, especially for large notecards
  • recent success correlates (but imperfectly) with continuing success: if it's cached in one frame, it's (only) probably still cached in the next
  • the more notecards a region reads, the sooner one will expire from cache after use
  • if the region restarts and you're likely to read a specific notecard soon, maybe pre-heat the cache with an async read (ignoring the results) to improve hit rate on the next sync read

Yup, that all was completely as expected, zero surprises there.  (Thankfully.)  But was great to get confirmation of two main points:

Assume the notecard may vanish during your loop, and it can occasionally take a weirdly long time to get to cache (so assuming it'll happen during the llGNL/llGNONL is a bad idea).

Shame they didn't answer the question of cache policy, but not having countered the comment, """ after the last usage of [any of the] 3 nc functions """, rather suggests LRU though, which is good (assuming they didn't either just not see it, or decide to keep that detail internal by just not saying anything).

Could probably test that by reading a notecard every couple seconds, alongside the existing duration testing that's been done.

  • Like 1
Link to comment
Share on other sites

7 hours ago, Frionil Fang said:

As per the test scripts in this thread, including mine, yes it returns EOF.

I don't know where this misconception that you need tthe line count comes from all of a sudden, you just need to call one of the async functions to cache the notecard, you don't need to handle the async event or do anything with what's returned.

I'm certainly going to (ab)use that style; adding the -Sync version will be a nice speed boost drop-in to existing dataserver-event based notecard reading, but having to service an async event to be able to use a sync function sounds like it's not very synchronous at all... and sometimes you just might want to get the data right there, right now (even if it takes a retry or two to get a proper return value). If the asset server is so knackered it can't fulfill that, I'm pretty sure there are more pressing issues and trying to do old async reading wouldn't be working great either.

Yes, I myself never get the # of notecard lines unless I want to display %done for the user.

Edited by Love Zhaoying
% not #
Link to comment
Share on other sites

5 hours ago, Bleuhazenfurfle said:

Shame they didn't answer the question of cache policy, but not having countered the comment, """ after the last usage of [any of the] 3 nc functions """, rather suggests LRU though, which is good (assuming they didn't either just not see it, or decide to keep that detail internal by just not saying anything).

Could probably test that by reading a notecard every couple seconds, alongside the existing duration testing that's been done.

They may be keeping options open, or hedging about current non-LRU behavior that's not so simply expressed… such as bugs:

Quote

[2024/01/30 12:21]  Rider Linden: Leviathan actually spotted a bug where cards might be kept for less time than necessary.  I'll get a fix for that into Hearts & Flowers. It didn't matter before because if the card got swapped out it would just go fetch it again.

 

  • Like 1
Link to comment
Share on other sites

Disclaimer, I haven't tested this, at all. Don't know if it even compiles just a draft, but here's what I'm thinking would be a way to load many notecards simultaneously as fast as possible in the new paradigm once llGetNotecardLineSync exists

key myNotecardRequest1;
key myNotecardRequest2;
key myNotecardRequest3;

/*
	To kick off a notecard read, call this function with your notecard name,
	Pass -1 to line, NULL_KEY to req_id and "" to text.

	The function will repeatedly call itself during the process.
*/
read_notecard_to_end(string notecard, integer line, key req_id, string text)
{
	@next;
	if (line >= 0)
	{
		if (text == EOF)
		{

			// Do whatever you want to do after the whole notecard is read here.
			// <YOUR CODE HERE>
			return;
		} else {
			// This is a valid line. `text` here is the text on `line` in `notecard`.
			// <YOUR CODE HERE>
		}
	}
	++line;
	text = llGetNotecardLineSync(notecard, line);
	if (text != NAK) jump next;
	key dataserver_req = llGetNotecardLine(notecard, line);
	llLinksetDataWrite("DSR_" + dataserver_req, llList2Json(JSON_OBJECT, [
		"n", notecard,
		"l", line,
		"r", req_id
	]));
}

default
{
	state_entry()
	{
		llLinksetDataDeleteFound("^DSR_*", ""); // Delete any leftover garbage.
	}

	touch_start(integer num_detected)
	{
		myNotecardRequest1 = llGenerateKey();
		myNotecardRequest2 = llGenerateKey();
		myNotecardRequest3 = llGenerateKey();
		read_notecard_to_end("Notecard 1", -1, myNotecardRequest1, "");
		read_notecard_to_end("Notecard 2", -1, myNotecardRequest2, "");
		read_notecard_to_end("Notecard 3", -1, myNotecardRequest3, "");
	}

	dataserver(key queryid, string data)
	{
		string jreq = llLinksetDataRead("DSR_" + (string)queryid);
		string notecard = llJsonGetValue(jreq, ["n"])
		integer line    = (integer)llJsonGetValue(jreq, ["l"]);
		key    req_id   = llJsonGetValue(jreq, ["r"])
		read_notecard_to_end(notecard, line,  req_id, data);
		llLinksetDataDelete("DSR_" + (string)queryid);
	}
}

 

Link to comment
Share on other sites

Hot take:

string notecard = "settings";

default
{
    touch_start(integer _)
    {
        llGetNumberOfNotecardLines(notecard);
    }

    dataserver(key __, string _)
    {
        integer line;
        string text;

        for (
            text = llGetNotecardLineSync(notecard, line);
            text != EOF && text != NAK;
            text = llGetNotecardLineSync(notecard, ++line)
        ) {
            llOwnerSay(text);
        }

        llOwnerSay((string)["Lines read: ", line]);

        if (text == NAK) {
            llOwnerSay("Cache interrupted!");
        }
    }
}

 

Edited by Wulfie Reanimator
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 70 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...