SL-11657 Separated expected from current inventory serial for better sync and to fix partial loads
parent
af011f9241
commit
301c5ae4e2
|
|
@ -269,6 +269,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
|
|||
mPixelArea(1024.f),
|
||||
mInventory(NULL),
|
||||
mInventorySerialNum(0),
|
||||
mExpectedInventorySerialNum(0),
|
||||
mInvRequestState(INVENTORY_REQUEST_STOPPED),
|
||||
mInvRequestXFerId(0),
|
||||
mInventoryDirty(FALSE),
|
||||
|
|
@ -2802,13 +2803,13 @@ void LLViewerObject::doUpdateInventory(
|
|||
{
|
||||
// best guess.
|
||||
perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), item->getPermissions().getGroup(), is_atomic);
|
||||
--mInventorySerialNum;
|
||||
--mExpectedInventorySerialNum;
|
||||
}
|
||||
else
|
||||
{
|
||||
// dummy it up.
|
||||
perm.setOwnerAndGroup(LLUUID::null, LLUUID::null, LLUUID::null, is_atomic);
|
||||
--mInventorySerialNum;
|
||||
--mExpectedInventorySerialNum;
|
||||
}
|
||||
}
|
||||
LLViewerInventoryItem* oldItem = item;
|
||||
|
|
@ -2816,7 +2817,11 @@ void LLViewerObject::doUpdateInventory(
|
|||
new_item->setPermissions(perm);
|
||||
mInventory->push_front(new_item);
|
||||
doInventoryCallback();
|
||||
++mInventorySerialNum;
|
||||
++mExpectedInventorySerialNum;
|
||||
}
|
||||
else if (is_new)
|
||||
{
|
||||
++mExpectedInventorySerialNum;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2883,7 +2888,7 @@ void LLViewerObject::moveInventory(const LLUUID& folder_id,
|
|||
if(!item->getPermissions().allowCopyBy(gAgent.getID()))
|
||||
{
|
||||
deleteInventoryItem(item_id);
|
||||
++mInventorySerialNum;
|
||||
++mExpectedInventorySerialNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3146,74 +3151,95 @@ S32 LLFilenameAndTask::sCount = 0;
|
|||
// static
|
||||
void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
|
||||
{
|
||||
LLUUID task_id;
|
||||
msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
|
||||
LLViewerObject* object = gObjectList.findObject(task_id);
|
||||
if(!object)
|
||||
{
|
||||
LL_WARNS() << "LLViewerObject::processTaskInv object "
|
||||
<< task_id << " does not exist." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
LLUUID task_id;
|
||||
msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
|
||||
LLViewerObject* object = gObjectList.findObject(task_id);
|
||||
if (!object)
|
||||
{
|
||||
LL_WARNS() << "LLViewerObject::processTaskInv object "
|
||||
<< task_id << " does not exist." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLFilenameAndTask* ft = new LLFilenameAndTask;
|
||||
ft->mTaskID = task_id;
|
||||
// we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
|
||||
msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
|
||||
LLFilenameAndTask* ft = new LLFilenameAndTask;
|
||||
ft->mTaskID = task_id;
|
||||
// we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
|
||||
msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
|
||||
|
||||
if (ft->mSerial < object->mInventorySerialNum)
|
||||
{
|
||||
// viewer did some changes to inventory that were not saved yet.
|
||||
LL_DEBUGS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client serial: " << object->mInventorySerialNum << LL_ENDL;
|
||||
object->mInventorySerialNum = ft->mSerial;
|
||||
}
|
||||
if (ft->mSerial == object->mInventorySerialNum)
|
||||
{
|
||||
// Loop Protection.
|
||||
// We received same serial twice.
|
||||
// Viewer did some changes to inventory that couldn't be saved server side
|
||||
// or something went wrong to cause serial to be out of sync
|
||||
LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL;
|
||||
object->mExpectedInventorySerialNum = ft->mSerial;
|
||||
}
|
||||
|
||||
std::string unclean_filename;
|
||||
msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
|
||||
ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
|
||||
if (ft->mSerial < object->mExpectedInventorySerialNum)
|
||||
{
|
||||
// out of date message, record to current serial for loop protection, but do not load it
|
||||
// just drop xfer to restart on idle
|
||||
if (ft->mSerial < object->mInventorySerialNum)
|
||||
{
|
||||
LL_WARNS() << "Somehow task serial decreased, out of order packet?" << LL_ENDL;
|
||||
}
|
||||
object->mInventorySerialNum = ft->mSerial;
|
||||
object->mInvRequestXFerId = 0;
|
||||
object->mInvRequestState = INVENTORY_REQUEST_STOPPED;
|
||||
}
|
||||
else if (ft->mSerial >= object->mExpectedInventorySerialNum)
|
||||
{
|
||||
object->mInventorySerialNum = ft->mSerial;
|
||||
object->mExpectedInventorySerialNum = ft->mSerial;
|
||||
|
||||
if(ft->mFilename.empty())
|
||||
{
|
||||
LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
|
||||
// mock up some inventory to make a drop target.
|
||||
if(object->mInventory)
|
||||
{
|
||||
object->mInventory->clear(); // will deref and delete it
|
||||
}
|
||||
else
|
||||
{
|
||||
object->mInventory = new LLInventoryObject::object_list_t();
|
||||
}
|
||||
LLPointer<LLInventoryObject> obj;
|
||||
obj = new LLInventoryObject(object->mID, LLUUID::null,
|
||||
LLAssetType::AT_CATEGORY,
|
||||
"Contents");
|
||||
object->mInventory->push_front(obj);
|
||||
object->doInventoryCallback();
|
||||
delete ft;
|
||||
return;
|
||||
}
|
||||
U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
|
||||
ft->mFilename, LL_PATH_CACHE,
|
||||
object->mRegionp->getHost(),
|
||||
TRUE,
|
||||
&LLViewerObject::processTaskInvFile,
|
||||
(void**)ft,
|
||||
LLXferManager::HIGH_PRIORITY);
|
||||
if (object->mInvRequestState == INVENTORY_XFER)
|
||||
{
|
||||
if (new_id > 0 && new_id != object->mInvRequestXFerId)
|
||||
{
|
||||
// we started new download.
|
||||
gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
|
||||
object->mInvRequestXFerId = new_id;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
object->mInvRequestState = INVENTORY_XFER;
|
||||
object->mInvRequestXFerId = new_id;
|
||||
}
|
||||
std::string unclean_filename;
|
||||
msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
|
||||
ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
|
||||
|
||||
if (ft->mFilename.empty())
|
||||
{
|
||||
LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
|
||||
// mock up some inventory to make a drop target.
|
||||
if (object->mInventory)
|
||||
{
|
||||
object->mInventory->clear(); // will deref and delete it
|
||||
}
|
||||
else
|
||||
{
|
||||
object->mInventory = new LLInventoryObject::object_list_t();
|
||||
}
|
||||
LLPointer<LLInventoryObject> obj;
|
||||
obj = new LLInventoryObject(object->mID, LLUUID::null,
|
||||
LLAssetType::AT_CATEGORY,
|
||||
"Contents");
|
||||
object->mInventory->push_front(obj);
|
||||
object->doInventoryCallback();
|
||||
delete ft;
|
||||
return;
|
||||
}
|
||||
U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
|
||||
ft->mFilename, LL_PATH_CACHE,
|
||||
object->mRegionp->getHost(),
|
||||
TRUE,
|
||||
&LLViewerObject::processTaskInvFile,
|
||||
(void**)ft,
|
||||
LLXferManager::HIGH_PRIORITY);
|
||||
if (object->mInvRequestState == INVENTORY_XFER)
|
||||
{
|
||||
if (new_id > 0 && new_id != object->mInvRequestXFerId)
|
||||
{
|
||||
// we started new download.
|
||||
gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
|
||||
object->mInvRequestXFerId = new_id;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
object->mInvRequestState = INVENTORY_XFER;
|
||||
object->mInvRequestXFerId = new_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status)
|
||||
|
|
@ -3227,6 +3253,13 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS
|
|||
&& ft->mSerial >= object->mInventorySerialNum)
|
||||
{
|
||||
object->mInventorySerialNum = ft->mSerial;
|
||||
LL_DEBUGS() << "Receiving inventory task file for serial " << object->mInventorySerialNum << " taskid: " << ft->mTaskID << LL_ENDL;
|
||||
if (ft->mSerial < object->mExpectedInventorySerialNum)
|
||||
{
|
||||
// User managed to change something while inventory was loading
|
||||
LL_DEBUGS() << "Processing file that is potentially out of date for task: " << ft->mTaskID << LL_ENDL;
|
||||
}
|
||||
|
||||
if (object->loadTaskInvFile(ft->mFilename))
|
||||
{
|
||||
|
||||
|
|
@ -3376,7 +3409,7 @@ void LLViewerObject::removeInventory(const LLUUID& item_id)
|
|||
msg->addUUIDFast(_PREHASH_ItemID, item_id);
|
||||
msg->sendReliable(mRegionp->getHost());
|
||||
deleteInventoryItem(item_id);
|
||||
++mInventorySerialNum;
|
||||
++mExpectedInventorySerialNum;
|
||||
}
|
||||
|
||||
bool LLViewerObject::isTextureInInventory(LLViewerInventoryItem* item)
|
||||
|
|
|
|||
|
|
@ -802,6 +802,7 @@ protected:
|
|||
typedef std::list<LLInventoryCallbackInfo*> callback_list_t;
|
||||
callback_list_t mInventoryCallbacks;
|
||||
S16 mInventorySerialNum;
|
||||
S16 mExpectedInventorySerialNum;
|
||||
|
||||
enum EInventoryRequestState
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue