LlUpdateKeyValue
Looking for the current API? Open the llUpdateKeyValue reference →
Wiki description
Start an asynchronous transaction to update a key-value pair associated with the script's Experience with the given key (
k) and value (v).Function notes
If
checked is set to TRUE then the update will only happen if original_value matches the current value in key-value store, otherwise the dataserver will return a failure along with the error XP_ERROR_RETRY_UPDATE. This can be used to create an in-use flag so that Atomicity can be achieved.As of Jan 1, 2016 maximum bytes is 1011 for key and 4095 for value for both LSO and Mono scripts.
Using llUpdateKeyValue to update a key that does not exist will not generate XP_ERROR_KEY_NOT_FOUND. Instead, it will generate a new key with the specified value, as if you had used llCreateKeyValue.
Return value notes
Returns a key that can be used to identify the corresponding dataserver event to determine if this command succeeded or failed and the results.
Caveats
- It is recommended that keys do not contain commas due to llKeysKeyValue returning keys in CSV format.
Examples
key trans;
default
{
state_entry()
{
trans = llUpdateKeyValue("FOO", "BLAH", TRUE, "BAR");
}
dataserver(key t, string value)
{
if (t == trans)
{
// our llUpdateKeyValue transaction is done
list result = llCSV2List(value);
if (llList2Integer(result, 0) == 1)
{
// the key-value pair was successfully updated
llSay(0, "New key-value pair was successfully updated");
}
else
{
integer error = llList2Integer(result, 1);
if(error == XP_ERROR_RETRY_UPDATE)
llSay(0, "Key-value update failed, checked value is out of date");
else
llSay(0, "Key-value update failed: " + llGetExperienceErrorMessage(error) );
}
}
}
}This script demonstrates how to avoid update conflicts (two scripts updating the store at the same time), performing fully atomic updates is more complicated. If all scripts writing to the key-value store abide by the virtual lock ($DB_Lock), and only do updates in update_db state, then all writes will be atomic.
key tid;
list tids;
default {
state_entry() {
state lock_db;
}
}
state lock_db {
state_entry() {
tid = llUpdateKeyValue("$DB_Lock", "LOCK", TRUE, "unlock");
}
dataserver(key did, string value) {
if(did == tid) {
string payload = llDeleteSubString(value, 0, 1);
if(llGetSubString(value+",", 0, 1) == "1,"){
llUpdateKeyValue("$DB_LockedBy", llDumpList2String([llGetOwner(),llGetKey(),llGetLinkKey(!!llGetLinkNumber()),llGetRegionName(),llGetPos(),llGetAttached()],":"), FALSE, "");
state update_db;
} else {
integer err = (integer)payload;
if(err == XP_ERROR_RETRY_UPDATE) {
llSay(0, "Database is already locked!");
} else {
llSay(0, "Key-value update failed: " + llGetExperienceErrorMessage(err) );
}
state error;
}
}
}
}
state update_db {
state_entry() {
tids = [
llUpdateKeyValue("CatsPermissable", "5", FALSE, ""),
llUpdateKeyValue("MonkeyMutations", "3", FALSE, ""),
llUpdateKeyValue("CodFlavorSupport", "NEVER", FALSE, "")
];
}
dataserver(key did, string value) {
integer i = llListFindList(tid, [did]);
if(~i) {
string payload = llDeleteSubString(value, 0, 1);
if(llGetSubString(value+",", 0, 1) == "1,"){
tids = llDeleteSubList(tids, i, i);
if(tids == []) {
state unlock_db;
}
} else {
llSay(0, "Key-value update failed: " + llGetExperienceErrorMessage((integer)payload) );
state error;
}
}
}
}
state unlock_db {
state_entry() {
tid = llUpdateKeyValue("$DB_Lock", "unlock", TRUE, "LOCK");
}
dataserver(key did, string value) {
if(did == tid) {
string payload = llDeleteSubString(value, 0, 1);
if(llGetSubString(value+",", 0, 1) == "1,"){
state done;
} else {
integer err = (integer)payload;
if(err == XP_ERROR_RETRY_UPDATE) {
llSay(0, "Someone has violated the database lock!");
} else {
llSay(0, "Key-value update failed: " + llGetExperienceErrorMessage(err) );
}
state error;
}
}
}
}
state done {
state_entry(){;}
}
state error {
state_entry(){;}
}See also: functions
Shared wiki helpers
The original page also injects shared parameter notes, caveats or issue information through these helpers. Their conditional MediaWiki logic is not reproduced here; inspect the preserved helper source for additional material.
Template:LSL Function/KeyValue
Original shared helper source (conditional wiki logic is not evaluated)
<noinclude>{{Multi-lang|category=LSL}}</noinclude>{{LSL Injection Test}}{{#if:
{{#vardefine:p_success_desc|A boolean specifying if the transaction succeeded (1) or not (0).}}
{{#vardefine:p_error_hover|An XP_ERROR_* flag that describes why the operation failed.}}
{{#vardefine:p_error_desc|An {{CAL|LSL Integer/experience_error{{#var:lang}}|XP_ERROR_*}} flag that describes why the operation failed.}}
{{#vardefine:p_cdl_desc|A string that is a comma-deliminated list}}
{{#vardefine:p_components_desc|varies depending upon success or failure of request}}
{{#vardefine:p_{{{d2_name|}}}_hover|{{#var:p_{{{d2_name|}}}_hover}}{{{d2_hover|}}}}}
{{#vardefine:p_{{{d3_name|}}}_hover|{{#var:p_{{{d3_name|}}}_hover}}{{{d3_hover|}}}}}
{{#vardefine:p_{{{d4_name|}}}_hover|{{#var:p_{{{d4_name|}}}_hover}}{{{d4_hover|}}}}}
{{#vardefine:p_{{{dl_name|}}}_hover|{{#var:p_{{{dl_name|}}}_hover}}{{{dl_hover|}}}}}
{{#if:{{{1|}}}<noinclude>*</noinclude>|{{LSL Function/KeyValue/Key|{{{1}}}|dataserver={{{dataserver|}}}}}}}
{{#if:{{{key|}}}|{{LSL Function/KeyValue/Key|{{{key}}}|dataserver={{{dataserver|}}}}}}}
{{#if:{{{2|}}}<noinclude>*</noinclude>|{{LSL Function/KeyValue/Value|{{{2}}}|dataserver={{{dataserver|}}}}}}}
{{#if:{{{value|}}}<noinclude>*</noinclude>|{{LSL Function/KeyValue/Value|{{{value}}}|Note! This value may contain commas.|dataserver={{{dataserver|}}}}}}}
{{#vardefine:p_{{{d2_name|}}}_desc|{{#var:p_{{{d2_name|}}}_desc}}{{{d2_desc|}}}}}
{{#vardefine:p_{{{d3_name|}}}_desc|{{#var:p_{{{d3_name|}}}_desc}}{{{d3_desc|}}}}}
{{#vardefine:p_{{{d4_name|}}}_desc|{{#var:p_{{{d4_name|}}}_desc}}{{{d4_desc|}}}}}
{{#vardefine:p_{{{dl_name|}}}_desc|{{#var:p_{{{dl_name|}}}_desc}}{{{dl_desc|}}}}}
<includeonly>
{{#ifeq:{{#var:article-type}}|event||{{#if:{{#pos:{{#var:moded}}|r}}{{#pos:{{#var:moded}}|u}}||{{#vardefine:hidden-text|{{#var:hidden-text}}
{{LSLC|Dataserver{{#var:lang}}}}{{#if:{{{mode|}}}|{{LSLC|Dataserver/{{{mode}}}{{#var:lang}}}}}}
}}}}}}
</includeonly>
{{#vardefine:table_text|{{PBR}}
The string containing a comma-delimited list ({{LSLPT|cdl}}). <code>llDumpList2String([ [[integer]] {{LSLPT|success}} ] + {{LSLPT|components}});</code>
* {{LSLPT|components}} vary depending upon success or failure of request.
* Failure: <code>{{LSLPT|cdl}} = [[llDumpList2String]]([ 0, [[integer]] {{LSLPT|error}}],",")</code>
* Success: <code>{{LSLPT|cdl}} = [[llDumpList2String]]([ 1{{#if:{{{d2_type|}}}{{{d2_name|}}}|, [[{{{d2_type}}}{{#var:lang}}|{{{d2_type}}}]] {{LSLPT|{{{d2_name}}}}}{{#if:{{{d3_type|}}}{{{d3_name|}}}|, [[{{{d3_type}}}{{#var:lang}}|{{{d3_type}}}]] {{LSLPT|{{{d3_name}}}}}{{#if:{{{d4_type|}}}{{{d4_name|}}}|, [[{{{d4_type}}}{{#var:lang}}|{{{d4_type}}}]] {{LSLPT|{{{d4_name}}}}}}}}}}} ]{{#if:{{{dl_name|}}}| + {{LSLPT|{{{dl_name|}}}}})}},",")</code>
===== String Components =====
{{{!}} style="margin-left:0em;"
{{LSL DefineRow|integer|2={{CAL|LSL Integer/boolean{{#var:lang}}|success}}|3={{#var:p_success_desc}}}}
{{LSL DefineRow|integer|2={{CAL|LSL Integer/experience_error{{#var:lang}}|error}}|3={{#var:p_error_desc}}}}
{{#if:{{{d2_name|}}}{{{d2_type|}}}|{{LSL DefineRow|1={{{d2_type|}}}|2={{#if:{{{d2_subtype|}}}|{{CAL|LSL {{ucfirst:{{{d2_type|}}}}}/{{{d2_subtype|}}}{{#var:lang}}|{{{d2_name|}}}}}|{{LSL_Parameter_Link|{{{d2_name|}}}}}}}|3={{#var:p_{{{d2_name|}}}_desc}}}}
{{#if:{{{d3_name|}}}{{{d3_type|}}}|{{LSL DefineRow|1={{{d3_type|}}}|2={{#if:{{{d3_subtype|}}}|{{CAL|LSL {{ucfirst:{{{d3_type|}}}}}/{{{d3_subtype|}}}{{#var:lang}}|{{{d3_name|}}}}}|{{LSL_Parameter_Link|{{{d3_name|}}}}}}}|3={{#var:p_{{{d3_name|}}}_desc}}}}
{{#if:{{{d4_name|}}}{{{d4_type|}}}|{{LSL DefineRow|1={{{d4_type|}}}|2={{#if:{{{d4_subtype|}}}|{{CAL|LSL {{ucfirst:{{{d4_type|}}}}}/{{{d4_subtype|}}}{{#var:lang}}|{{{d4_name|}}}}}|{{LSL_Parameter_Link|{{{d4_name|}}}}}}}|3={{#var:p_{{{d4_name|}}}_desc}}}}
}}}}}}
{{#if:{{{dl_name|}}}|{{LSL DefineRow|1=list|2={{#if:{{{dl_subtype|}}}|{{CAL|LSL List/{{{dl_subtype|}}}{{#var:lang}}|{{{dl_name|}}}}}|{{LSL_Parameter_Link|{{{dl_name|}}}}}}}|3={{#var:p_{{{dl_name|}}}_desc}}}}}}
{{!}}}
}}
{{#if:{{{dataserver|}}}|
{{#vardefine:p_{{{d2_name|}}}_hover|}}
{{#vardefine:p_{{{d3_name|}}}_hover|}}
{{#vardefine:p_{{{d4_name|}}}_hover|}}
{{#vardefine:p_{{{dl_name|}}}_hover|}}
{{#vardefine:p_{{{d2_name|}}}_desc|}}
{{#vardefine:p_{{{d3_name|}}}_desc|}}
{{#vardefine:p_{{{d4_name|}}}_desc|}}
{{#vardefine:p_{{{dl_name|}}}_desc|}}
|
{{#vardefine:spec|{{#var:spec}}
* Maximum memory storage: 128 MiB
<h4>Dataserver</h4>
The [[dataserver]] callback parameters are:
* A key containing the {{LSLGC|Key/handle|handle}} returned from [[{{#var:name}}]]
* A string containing a comma-delimited list ({{LSLPT|cdl}}). <code>llDumpList2String([ [[integer]] {{LSLPT|success}} ] + {{LSLPT|components}});</code>
** {{LSLPT|components}} vary depending upon success or failure of request.
** Failure: <code>{{LSLPT|cdl}} = [[llDumpList2String]]([ 0, [[integer]] {{LSLPT|error}}],",")</code>
** Success: <code>{{LSLPT|cdl}} = [[llDumpList2String]]([ 1{{#if:{{{d2_type|}}}{{{d2_name|}}}|, [[{{{d2_type}}}{{#var:lang}}|{{{d2_type}}}]] {{LSLPT|{{{d2_name}}}}}{{#if:{{{d3_type|}}}{{{d3_name|}}}|, [[{{{d3_type}}}{{#var:lang}}|{{{d3_type}}}]] {{LSLPT|{{{d3_name}}}}}{{#if:{{{d4_type|}}}{{{d4_name|}}}|, [[{{{d4_type}}}{{#var:lang}}|{{{d4_type}}}]] {{LSLPT|{{{d4_name}}}}}}}}}}} ]{{#if:{{{dl_name|}}}| + {{LSLPT|{{{dl_name|}}}}})}},",")</code>
===== String Components =====
{{{!}} style="margin-left:0em;"
{{LSL DefineRow|integer|2={{CAL|LSL Integer/boolean{{#var:lang}}|success}}|3={{#var:p_success_desc}}}}
{{LSL DefineRow|integer|2={{CAL|LSL Integer/experience_error{{#var:lang}}|error}}|3={{#var:p_error_desc}}}}
{{#if:{{{d2_name|}}}{{{d2_type|}}}|{{LSL DefineRow|1={{{d2_type|}}}|2={{#if:{{{d2_subtype|}}}|{{CAL|LSL {{ucfirst:{{{d2_type|}}}}}/{{{d2_subtype|}}}{{#var:lang}}|{{{d2_name|}}}}}|{{LSL_Parameter_Link|{{{d2_name|}}}}}}}|3={{#var:p_{{{d2_name|}}}_desc}}}}
{{#if:{{{d3_name|}}}{{{d3_type|}}}|{{LSL DefineRow|1={{{d3_type|}}}|2={{#if:{{{d3_subtype|}}}|{{CAL|LSL {{ucfirst:{{{d3_type|}}}}}/{{{d3_subtype|}}}{{#var:lang}}|{{{d3_name|}}}}}|{{LSL_Parameter_Link|{{{d3_name|}}}}}}}|3={{#var:p_{{{d3_name|}}}_desc}}}}
{{#if:{{{d4_name|}}}{{{d4_type|}}}|{{LSL DefineRow|1={{{d4_type|}}}|2={{#if:{{{d4_subtype|}}}|{{CAL|LSL {{ucfirst:{{{d4_type|}}}}}/{{{d4_subtype|}}}{{#var:lang}}|{{{d4_name|}}}}}|{{LSL_Parameter_Link|{{{d4_name|}}}}}}}|3={{#var:p_{{{d4_name|}}}_desc}}}}
}}}}}}
{{#if:{{{dl_name|}}}|{{LSL DefineRow|1=list|2={{#if:{{{dl_subtype|}}}|{{CAL|LSL List/{{{dl_subtype|}}}{{#var:lang}}|{{{dl_name|}}}}}|{{LSL_Parameter_Link|{{{dl_name|}}}}}}}|3={{#var:p_{{{dl_name|}}}_desc}}}}}}
{{!}}}
}}
}}
<!--
{{#if:{{{nocaveats|}}}||{{#if:{{{nogroup|}}}|
{{#vardefine:caveats|{{#var:caveats}}}}
*
}}}}
{{#if:{{#var:key_stuff}}||
{{#vardefine:key_stuff|*}}
{{#vardefine:notes|{{#var:notes}}}}
}}
-->
}}<noinclude>
{| {{Prettytable}}
|-{{Hl2}}
! #var
! value
|-
{{VarPair|p_{{{1}}}_desc}}
|-
{{VarPair|p_{{{2}}}_desc}}
|-
{{VarPair|p_{{{value}}}_desc}}
|-
{{VarPair|spec}}
|-
{{VarPair|caveats}}
|-
{{VarPair|table_text}}
|}
</noinclude>{{#if:{{{dataserver|}}}|{{#var:table_text}}}}Template:LSL Function/Experience
Original shared helper source (conditional wiki logic is not evaluated)
<noinclude>{{Multi-lang|category=LSL}}</noinclude>{{LSL Injection Test}}{{#if:
{{#vardefine:notes|{{#var:notes}}
<h4>Compiling</h4>
For a script to be associated with an {{LSLGC|Experience}}...
* It must be compiled with a client that is Experience aware,
* The "Use Experience" checkbox must be checked,
* And one of the users Experience keys selected.
{{LSL Tip|Not all [[TPV]]s have this functionality.}}
}}
{{#ifeq:{{{1|}}}<noinclude>true</noinclude>|true|
{{#vardefine:header_footnote_last|{{#var:header_footnote_last}}{{PBR}}
For this {{#var:article_type}} to work, the script must be compiled into an {{LSLGC|Experience}}.{{PBR}}
}}
{{#vardefine:caveats|{{#var:caveats}}
* If you recompile a script that was previously associated with an Experience but do so with a client that lacks the ability to compile scripts into an experience the script will lose the associated Experience.
}}
}}
}}<noinclude>
{| {{Prettytable}}
|-{{Hl2}}
! #var
! value
|-
{{VarPair|header_footnote_last}}
|-
{{VarPair|spec}}
|-
{{VarPair|caveats}}
|-
{{VarPair|notes}}
|}
</noinclude>Original wiki source
Some wiki templates and tables need their original context. View this article on the Second Life Wiki. Technical wording and examples are retained from the source; historical guidance may differ from current behavior.