LlUpdateKeyValue
| 首页 | 函数 | 事件 | 类型 | 操作符 | 常数 | Flow Control | Script Library | Categorized Library | Tutorials |
| 函数名 |
|---|
| Function: key llUpdateKeyValue( string k, string v, integer checked, string original_value ); |
| 参数:•字符串k(string k)–键值对的键
•字符串v(string v)–键值对的值。最多2047个字符,如果使用单声道,则为4095个字符。 •整数已检查(integer checked)–如果为真,则只有原始_值与键值存储区中的值匹配时才会进行更新。 •字符串原始值(string original_value)–要与键值存储区中的当前值进行比较的值。 如果checked设置为TRUE,则只有当原始值与键值存储区中的当前值匹配时,才会进行更新,否则数据服务器将返回失败,并返回错误XP_error_RETRY_update。这可以用来创建一个正在使用的标志,这样就可以实现原子性。 |
| 返回值:返回一个句柄(键),该句柄可用于标识相应的数据服务器事件,以确定此命令是成功还是失败以及结果。
截至2016年1月1日,LSO和Mono脚本的最大字节数分别为1011和4095。 使用llUpdateKeyValue更新不存在的密钥将不会生成XP\u ERROR\u key unt\u FOUND。相反,它将生成一个具有指定值的新键,就像您使用了llCreateKeyValue一样。 要使此功能正常工作,必须将脚本编译为一个体验Experience。 |
| 注意事项 |
|---|
| 数据服务器回调参数为:
包含从llUpdateKeyValue返回的句柄的键 包含逗号分隔列表(cdl)的字符串。llDumpList2String([integer success]+组件); 组件根据请求的成功或失败而变化。 失败:cdl=llDumpList2String([0,整数错误],“,”) 成功:cdl=llDumpList2String([1,字符串值],“,”) 字符串组件 •整数成功–一个布尔值,指定事务是否成功(1)或否(0)。 •整数错误–描述操作失败原因的XP_error_x标志。 •字符串值–键值对的值。最多2047个字符,如果使用单声道,则为4095个字符。注意!此值可能包含逗号。 如果重新编译以前与体验相关联的脚本,但对缺乏将脚本编译为体验能力的客户端执行此操作,则该脚本将丢失关联的体验。 由于llKeysKeyValue以CSV格式返回密钥,建议密钥不包含逗号。 |
| 示例 |
|---|
示例1
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) );
}
}
}
}
这个脚本演示了如何避免更新冲突(两个脚本同时更新存储),执行完全原子更新更为复杂。如果所有写入键值存储区的脚本都遵守虚拟锁($DB_lock),并且只在update_DB状态下进行更新,则所有写入都将是原子的。
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(){;}
}
|
| 相关函数 |
|---|
| llGetExperienceErrorMessage |
| 相关事件 |
|---|
| 无 |