aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llinventorymodel.cpp
diff options
context:
space:
mode:
authorunknown2008-12-29 17:53:13 -0700
committerunknown2008-12-29 17:53:13 -0700
commit78fb2791164591a3b7f853267370e85ee7857d4a (patch)
tree92a879624655a2143e85a85c3a34e43b2329501b /linden/indra/newview/llinventorymodel.cpp
parent1.1 wip copy (diff)
downloadmeta-impy-78fb2791164591a3b7f853267370e85ee7857d4a.zip
meta-impy-78fb2791164591a3b7f853267370e85ee7857d4a.tar.gz
meta-impy-78fb2791164591a3b7f853267370e85ee7857d4a.tar.bz2
meta-impy-78fb2791164591a3b7f853267370e85ee7857d4a.tar.xz
Added inventory changes for one method of inventory loss and upcoming new inv capabilities
Diffstat (limited to 'linden/indra/newview/llinventorymodel.cpp')
-rw-r--r--linden/indra/newview/llinventorymodel.cpp533
1 files changed, 331 insertions, 202 deletions
diff --git a/linden/indra/newview/llinventorymodel.cpp b/linden/indra/newview/llinventorymodel.cpp
index b1e3017..73f0fb3 100644
--- a/linden/indra/newview/llinventorymodel.cpp
+++ b/linden/indra/newview/llinventorymodel.cpp
@@ -73,7 +73,6 @@ F32 LLInventoryModel::sMinTimeBetweenFetches = 0.3f;
73F32 LLInventoryModel::sMaxTimeBetweenFetches = 10.f; 73F32 LLInventoryModel::sMaxTimeBetweenFetches = 10.f;
74BOOL LLInventoryModel::sTimelyFetchPending = FALSE; 74BOOL LLInventoryModel::sTimelyFetchPending = FALSE;
75LLFrameTimer LLInventoryModel::sFetchTimer; 75LLFrameTimer LLInventoryModel::sFetchTimer;
76LLInventoryModel::cat_map_t LLInventoryModel::sBulkFetchMap;
77S16 LLInventoryModel::sBulkFetchCount = 0; 76S16 LLInventoryModel::sBulkFetchCount = 0;
78 77
79// RN: for some reason, using std::queue in the header file confuses the compiler which things it's an xmlrpc_queue 78// RN: for some reason, using std::queue in the header file confuses the compiler which things it's an xmlrpc_queue
@@ -85,7 +84,7 @@ static std::deque<LLUUID> sFetchQueue;
85 84
86//BOOL decompress_file(const char* src_filename, const char* dst_filename); 85//BOOL decompress_file(const char* src_filename, const char* dst_filename);
87const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f; 86const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;
88const S32 MAX_FETCH_RETRIES = 5; 87const S32 MAX_FETCH_RETRIES = 10;
89const char CACHE_FORMAT_STRING[] = "%s.inv"; 88const char CACHE_FORMAT_STRING[] = "%s.inv";
90const char* NEW_CATEGORY_NAME = "New Folder"; 89const char* NEW_CATEGORY_NAME = "New Folder";
91const char* NEW_CATEGORY_NAMES[LLAssetType::AT_COUNT] = 90const char* NEW_CATEGORY_NAMES[LLAssetType::AT_COUNT] =
@@ -990,13 +989,24 @@ BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer)
990// Call this method when it's time to update everyone on a new state, 989// Call this method when it's time to update everyone on a new state,
991// by default, the inventory model will not update observers 990// by default, the inventory model will not update observers
992// automatically. 991// automatically.
993void LLInventoryModel::notifyObservers() 992// The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328]
993void LLInventoryModel::notifyObservers(const std::string service_name)
994{ 994{
995 for (observer_list_t::iterator iter = mObservers.begin(); 995 for (observer_list_t::iterator iter = mObservers.begin();
996 iter != mObservers.end(); ) 996 iter != mObservers.end(); )
997 { 997 {
998 LLInventoryObserver* observer = *iter; 998 LLInventoryObserver* observer = *iter;
999 observer->changed(mModifyMask); 999
1000 if (service_name.empty())
1001 {
1002 observer->changed(mModifyMask);
1003 }
1004 else
1005 {
1006 observer->mMessageName = service_name;
1007 observer->changed(mModifyMask);
1008 }
1009
1000 // safe way to incrament since changed may delete entries! (@!##%@!@&*!) 1010 // safe way to incrament since changed may delete entries! (@!##%@!@&*!)
1001 iter = mObservers.upper_bound(observer); 1011 iter = mObservers.upper_bound(observer);
1002 } 1012 }
@@ -1038,6 +1048,79 @@ void LLInventoryModel::mock(const LLUUID& root_id)
1038} 1048}
1039*/ 1049*/
1040 1050
1051//If we get back a normal response, handle it here
1052void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content)
1053{
1054 start_new_inventory_observer();
1055
1056 /*LLUUID agent_id;
1057 agent_id = content["agent_id"].asUUID();
1058 if(agent_id != gAgent.getID())
1059 {
1060 llwarns << "Got a inventory update for the wrong agent: " << agent_id
1061 << llendl;
1062 return;
1063 }*/
1064 item_array_t items;
1065 update_map_t update;
1066 S32 count = content["items"].size();
1067 bool all_one_folder = true;
1068 LLUUID folder_id;
1069 // Does this loop ever execute more than once? -Gigs
1070 for(S32 i = 0; i < count; ++i)
1071 {
1072 LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
1073 titem->unpackMessage(content["items"][i]);
1074
1075 lldebugs << "LLInventoryModel::messageUpdateCore() item id:"
1076 << titem->getUUID() << llendl;
1077 items.push_back(titem);
1078 // examine update for changes.
1079 LLViewerInventoryItem* itemp = gInventory.getItem(titem->getUUID());
1080 if(itemp)
1081 {
1082 if(titem->getParentUUID() == itemp->getParentUUID())
1083 {
1084 update[titem->getParentUUID()];
1085 }
1086 else
1087 {
1088 ++update[titem->getParentUUID()];
1089 --update[itemp->getParentUUID()];
1090 }
1091 }
1092 else
1093 {
1094 ++update[titem->getParentUUID()];
1095 }
1096 if (folder_id.isNull())
1097 {
1098 folder_id = titem->getParentUUID();
1099 }
1100 else
1101 {
1102 all_one_folder = false;
1103 }
1104 }
1105
1106 U32 changes = 0x0;
1107 //as above, this loop never seems to loop more than once per call
1108 for (item_array_t::iterator it = items.begin(); it != items.end(); ++it)
1109 {
1110 changes |= gInventory.updateItem(*it);
1111 }
1112 gInventory.notifyObservers("fetchinventory");
1113 gViewerWindow->getWindow()->decBusyCount();
1114}
1115
1116//If we get back an error (not found, etc...), handle it here
1117void LLInventoryModel::fetchInventoryResponder::error(U32 status, const std::string& reason)
1118{
1119 llinfos << "fetchInventory::error "
1120 << status << ": " << reason << llendl;
1121 gInventory.notifyObservers("fetchinventory");
1122}
1123
1041void LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id) 1124void LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id)
1042{ 1125{
1043 LLViewerInventoryCategory* cat = getCategory(folder_id); 1126 LLViewerInventoryCategory* cat = getCategory(folder_id);
@@ -1065,21 +1148,31 @@ void LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id)
1065} 1148}
1066 1149
1067//Initialize statics. 1150//Initialize statics.
1068LLAlertDialog* LLInventoryModel::fetchDescendentsResponder::sRetryDialog=NULL;
1069LLSD LLInventoryModel::fetchDescendentsResponder::sRetrySD;
1070
1071bool LLInventoryModel::isBulkFetchProcessingComplete() 1151bool LLInventoryModel::isBulkFetchProcessingComplete()
1072{ 1152{
1073 return ( (sFetchQueue.empty() 1153 return ( (sFetchQueue.empty()
1074 && sBulkFetchMap.empty() 1154 && sBulkFetchCount<=0) ? TRUE : FALSE ) ;
1075 && sBulkFetchCount==0) ? TRUE : FALSE ) ;
1076} 1155}
1077 1156
1157class fetchDescendentsResponder: public LLHTTPClient::Responder
1158{
1159 public:
1160 fetchDescendentsResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
1161 //fetchDescendentsResponder() {};
1162 void result(const LLSD& content);
1163 void error(U32 status, const std::string& reason);
1164 public:
1165 typedef std::vector<LLViewerInventoryCategory*> folder_ref_t;
1166 protected:
1167 LLSD mRequestSD;
1168};
1169
1078//If we get back a normal response, handle it here 1170//If we get back a normal response, handle it here
1079void LLInventoryModel::fetchDescendentsResponder::result(const LLSD& content) 1171void fetchDescendentsResponder::result(const LLSD& content)
1080{ 1172{
1081 if (content.has("folders")) 1173 if (content.has("folders"))
1082 { 1174 {
1175
1083 for(LLSD::array_const_iterator folder_it = content["folders"].beginArray(); 1176 for(LLSD::array_const_iterator folder_it = content["folders"].beginArray();
1084 folder_it != content["folders"].endArray(); 1177 folder_it != content["folders"].endArray();
1085 ++folder_it) 1178 ++folder_it)
@@ -1087,19 +1180,54 @@ void LLInventoryModel::fetchDescendentsResponder::result(const LLSD& content)
1087 LLSD folder_sd = *folder_it; 1180 LLSD folder_sd = *folder_it;
1088 1181
1089 1182
1090 LLUUID agent_id = folder_sd["agent-id"]; 1183 //LLUUID agent_id = folder_sd["agent_id"];
1091 1184
1092 if(agent_id != gAgent.getID()) //This should never happen. 1185 //if(agent_id != gAgent.getID()) //This should never happen.
1093 { 1186 //{
1094 llwarns << "Got a UpdateInventoryItem for the wrong agent." 1187 // llwarns << "Got a UpdateInventoryItem for the wrong agent."
1095 << llendl; 1188 // << llendl;
1096 break; 1189 // break;
1097 } 1190 //}
1098 LLUUID parent_id = folder_sd["folder-id"]; 1191
1099 LLUUID owner_id = folder_sd["owner-id"]; 1192 LLUUID parent_id = folder_sd["folder_id"];
1193 LLUUID owner_id = folder_sd["owner_id"];
1100 S32 version = (S32)folder_sd["version"].asInteger(); 1194 S32 version = (S32)folder_sd["version"].asInteger();
1101 S32 descendents = (S32)folder_sd["descendents"].asInteger(); 1195 S32 descendents = (S32)folder_sd["descendents"].asInteger();
1102 LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id); 1196 LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id);
1197
1198 if (parent_id.isNull())
1199 {
1200 LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
1201 for(LLSD::array_const_iterator item_it = folder_sd["items"].beginArray();
1202 item_it != folder_sd["items"].endArray();
1203 ++item_it)
1204 {
1205 LLUUID lost_uuid = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
1206 if (lost_uuid.notNull())
1207 {
1208 LLSD item = *item_it;
1209 titem->unpackMessage(item);
1210
1211 LLInventoryModel::update_list_t update;
1212 LLInventoryModel::LLCategoryUpdate new_folder(lost_uuid, 1);
1213 update.push_back(new_folder);
1214 gInventory.accountForUpdate(update);
1215
1216 titem->setParent(lost_uuid);
1217 titem->updateParentOnServer(FALSE);
1218 gInventory.updateItem(titem);
1219 gInventory.notifyObservers("fetchDescendents");
1220
1221 }
1222 }
1223 }
1224
1225 LLViewerInventoryCategory* pcat = gInventory.getCategory(parent_id);
1226 if (!pcat)
1227 {
1228 continue;
1229 }
1230
1103 for(LLSD::array_const_iterator category_it = folder_sd["categories"].beginArray(); 1231 for(LLSD::array_const_iterator category_it = folder_sd["categories"].beginArray();
1104 category_it != folder_sd["categories"].endArray(); 1232 category_it != folder_sd["categories"].endArray();
1105 ++category_it) 1233 ++category_it)
@@ -1107,7 +1235,7 @@ void LLInventoryModel::fetchDescendentsResponder::result(const LLSD& content)
1107 LLSD category = *category_it; 1235 LLSD category = *category_it;
1108 tcategory->fromLLSD(category); 1236 tcategory->fromLLSD(category);
1109 1237
1110 if (sFullFetchStarted) 1238 if (LLInventoryModel::sFullFetchStarted)
1111 { 1239 {
1112 sFetchQueue.push_back(tcategory->getUUID()); 1240 sFetchQueue.push_back(tcategory->getUUID());
1113 } 1241 }
@@ -1139,37 +1267,37 @@ void LLInventoryModel::fetchDescendentsResponder::result(const LLSD& content)
1139 } 1267 }
1140 } 1268 }
1141 1269
1142 if (content.has("bad-folders")) 1270 if (content.has("bad_folders"))
1143 { 1271 {
1144 for(LLSD::array_const_iterator folder_it = content["bad-folders"].beginArray(); 1272 for(LLSD::array_const_iterator folder_it = content["bad_folders"].beginArray();
1145 folder_it != content["bad-folders"].endArray(); 1273 folder_it != content["bad_folders"].endArray();
1146 ++folder_it) 1274 ++folder_it)
1147 { 1275 {
1148 LLSD folder_sd = *folder_it; 1276 LLSD folder_sd = *folder_it;
1149 1277
1150 //These folders failed on the dataserver. We probably don't want to retry them. 1278 //These folders failed on the dataserver. We probably don't want to retry them.
1151 llinfos << "Folder " << folder_sd["folder-id"].asString() 1279 llinfos << "Folder " << folder_sd["folder_id"].asString()
1152 << "Error: " << folder_sd["error"].asString() << llendl; 1280 << "Error: " << folder_sd["error"].asString() << llendl;
1153 } 1281 }
1154 } 1282 }
1155 1283
1156 LLInventoryModel::incrBulkFetch(-1); 1284 LLInventoryModel::incrBulkFetch(-1);
1157 1285
1158 if (isBulkFetchProcessingComplete()) 1286 if (LLInventoryModel::isBulkFetchProcessingComplete())
1159 { 1287 {
1160 llinfos << "Inventory fetch completed" << llendl; 1288 llinfos << "Inventory fetch completed" << llendl;
1161 if (sFullFetchStarted) 1289 if (LLInventoryModel::sFullFetchStarted)
1162 { 1290 {
1163 sAllFoldersFetched = TRUE; 1291 LLInventoryModel::sAllFoldersFetched = TRUE;
1164 } 1292 }
1165 stopBackgroundFetch(); 1293 LLInventoryModel::stopBackgroundFetch();
1166 } 1294 }
1167 1295
1168 gInventory.notifyObservers(); 1296 gInventory.notifyObservers("fetchDescendents");
1169} 1297}
1170 1298
1171//If we get back an error (not found, etc...), handle it here 1299//If we get back an error (not found, etc...), handle it here
1172void LLInventoryModel::fetchDescendentsResponder::error(U32 status, const std::string& reason) 1300void fetchDescendentsResponder::error(U32 status, const std::string& reason)
1173{ 1301{
1174 llinfos << "fetchDescendentsResponder::error " 1302 llinfos << "fetchDescendentsResponder::error "
1175 << status << ": " << reason << llendl; 1303 << status << ": " << reason << llendl;
@@ -1183,61 +1311,22 @@ void LLInventoryModel::fetchDescendentsResponder::error(U32 status, const std::s
1183 ++folder_it) 1311 ++folder_it)
1184 { 1312 {
1185 LLSD folder_sd = *folder_it; 1313 LLSD folder_sd = *folder_it;
1186 sRetrySD["folders"].append(folder_sd); 1314 LLUUID folder_id = folder_sd["folder_id"];
1187 } 1315 sFetchQueue.push_front(folder_id);
1188 sMinTimeBetweenFetches = 10.0f; //Add 10 seconds for every time out in this sequence.
1189
1190 if (!sRetryDialog) //The dialog isn't up. Prompt the resident.
1191 {
1192 sRetryDialog = gViewerWindow->alertXml("RetryFetchInventoryDescendents", onClickRetry, this);
1193 } 1316 }
1194 } 1317 }
1195 else 1318 else
1196 { 1319 {
1197 if (isBulkFetchProcessingComplete()) 1320 if (LLInventoryModel::isBulkFetchProcessingComplete())
1198 { 1321 {
1199 if (sFullFetchStarted) 1322 if (LLInventoryModel::sFullFetchStarted)
1200 { 1323 {
1201 sAllFoldersFetched = TRUE; 1324 LLInventoryModel::sAllFoldersFetched = TRUE;
1202 } 1325 }
1203 stopBackgroundFetch(); 1326 LLInventoryModel::stopBackgroundFetch();
1204 } 1327 }
1205 } 1328 }
1206 gInventory.notifyObservers(); 1329 gInventory.notifyObservers("fetchDescendents");
1207}
1208
1209void LLInventoryModel::fetchDescendentsResponder::onClickRetry(S32 option, void* userdata)
1210{
1211 if (option == 0)
1212 {
1213 std::string url;
1214
1215 LLViewerRegion * agent_region = gAgent.getRegion();
1216 if (agent_region)
1217 {
1218 url = agent_region->getCapability("FetchInventoryDescendents");
1219 }
1220
1221 if (!url.empty()) //Capability found. Build up LLSD and use it.
1222 {
1223 LLSD body = sRetrySD;
1224 LLInventoryModel::incrBulkFetch(1);
1225 LLHTTPClient::post(url, body, new LLInventoryModel::fetchDescendentsResponder(body),300);
1226 }
1227 }
1228 else
1229 {
1230 if (isBulkFetchProcessingComplete())
1231 {
1232 if (sFullFetchStarted)
1233 {
1234 sAllFoldersFetched = TRUE;
1235 }
1236 stopBackgroundFetch();
1237 }
1238 }
1239 sRetryDialog=NULL;
1240 sRetrySD.clear();
1241} 1330}
1242 1331
1243//static Bundle up a bunch of requests to send all at once. 1332//static Bundle up a bunch of requests to send all at once.
@@ -1250,7 +1339,7 @@ void LLInventoryModel::bulkFetch(std::string url)
1250 1339
1251 S16 max_concurrent_fetches=8; 1340 S16 max_concurrent_fetches=8;
1252 F32 new_min_time = 0.5f; //HACK! Clean this up when old code goes away entirely. 1341 F32 new_min_time = 0.5f; //HACK! Clean this up when old code goes away entirely.
1253 if (sMinTimeBetweenFetches <= new_min_time) sMinTimeBetweenFetches=new_min_time; //HACK! See above. 1342 if (sMinTimeBetweenFetches < new_min_time) sMinTimeBetweenFetches=new_min_time; //HACK! See above.
1254 1343
1255 if(gDisconnected 1344 if(gDisconnected
1256 || sBulkFetchCount > max_concurrent_fetches 1345 || sBulkFetchCount > max_concurrent_fetches
@@ -1263,84 +1352,83 @@ void LLInventoryModel::bulkFetch(std::string url)
1263 //redundant requests. When we get rid of the old code entirely, we can change 1352 //redundant requests. When we get rid of the old code entirely, we can change
1264 //the dequeue to a map. In the new model, there is no benefit to queue order. 1353 //the dequeue to a map. In the new model, there is no benefit to queue order.
1265 U32 folder_count=0; 1354 U32 folder_count=0;
1266 U32 max_batch_size=10; 1355 U32 max_batch_size=5;
1267 while( !(sFetchQueue.empty() ) ) 1356
1268 { 1357 U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1;
1269 LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front()); 1358
1270 1359 LLSD body;
1271 if (cat) 1360 LLSD body_lib;
1272 { 1361 while( !(sFetchQueue.empty() ) && (folder_count < max_batch_size) )
1273 if ( !gInventory.isCategoryComplete(cat->getUUID()) ) //grab this folder. 1362 {
1274 { 1363 if (sFetchQueue.front().isNull()) //DEV-17797
1275 sBulkFetchMap[(cat->getUUID())] = cat; 1364 {
1276 } 1365 LLSD folder_sd;
1277 else if (sFullFetchStarted) 1366 folder_sd["folder_id"] = LLUUID::null.asString();
1278 { //Already have this folder but append child folders to list. 1367 folder_sd["owner_id"] = gAgent.getID();
1279 // add all children to queue 1368 folder_sd["sort_order"] = (LLSD::Integer)sort_order;
1280 parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID()); 1369 folder_sd["fetch_folders"] = (LLSD::Boolean)FALSE;
1281 if (cat_it != gInventory.mParentChildCategoryTree.end()) 1370 folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
1282 { 1371 body["folders"].append(folder_sd);
1283 cat_array_t* child_categories = cat_it->second; 1372 folder_count++;
1284 1373 }
1285 for (S32 child_num = 0; child_num < child_categories->count(); child_num++) 1374 else
1286 { 1375 {
1287 sFetchQueue.push_back(child_categories->get(child_num)->getUUID()); 1376
1288 }
1289 }
1290 1377
1291 } 1378 LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front());
1292 } 1379
1380 if (cat)
1381 {
1382 if ( LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
1383 {
1384 LLSD folder_sd;
1385 folder_sd["folder_id"] = cat->getUUID();
1386 folder_sd["owner_id"] = cat->getOwnerID();
1387 folder_sd["sort_order"] = (LLSD::Integer)sort_order;
1388 folder_sd["fetch_folders"] = TRUE; //(LLSD::Boolean)sFullFetchStarted;
1389 folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
1390
1391 if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
1392 body_lib["folders"].append(folder_sd);
1393 else
1394 body["folders"].append(folder_sd);
1395 folder_count++;
1396 }
1397 if (sFullFetchStarted)
1398 { //Already have this folder but append child folders to list.
1399 // add all children to queue
1400 parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID());
1401 if (cat_it != gInventory.mParentChildCategoryTree.end())
1402 {
1403 cat_array_t* child_categories = cat_it->second;
1404
1405 for (S32 child_num = 0; child_num < child_categories->count(); child_num++)
1406 {
1407 sFetchQueue.push_back(child_categories->get(child_num)->getUUID());
1408 }
1409 }
1410
1411 }
1412 }
1413 }
1293 sFetchQueue.pop_front(); 1414 sFetchQueue.pop_front();
1294 } 1415 }
1295 1416
1296
1297 if (!sBulkFetchMap.empty()) //There's stuff to fetch.
1298 {
1299 U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1;
1300
1301 LLSD body;
1302
1303 cat_map_t::iterator iter=sBulkFetchMap.begin();
1304 while( iter!=sBulkFetchMap.end() && (folder_count < max_batch_size) )
1305 {
1306 LLViewerInventoryCategory* cat = iter->second;
1307
1308 if (cat && !gInventory.isCategoryComplete(cat->getUUID()) ) //Category exists
1309 {
1310 BOOL fetchItems=TRUE;
1311 if ( sFullFetchStarted
1312 && gInventory.isCategoryComplete(cat->getUUID()) )
1313 {
1314 fetchItems=FALSE;
1315 }
1316
1317 LLSD folder_sd;
1318 folder_sd["folder-id"] = cat->getUUID();
1319 folder_sd["owner-id"] = cat->getOwnerID();
1320 folder_sd["sort-order"] = (LLSD::Integer)sort_order;
1321 folder_sd["fetch-folders"] = (LLSD::Boolean)sFullFetchStarted;
1322 folder_sd["fetch-items"] = (LLSD::Boolean)fetchItems;
1323 body["folders"].append(folder_sd);
1324
1325 folder_count++;
1326 }
1327 sBulkFetchMap.erase(iter);
1328 iter=sBulkFetchMap.begin();
1329 }
1330
1331 if (iter == sBulkFetchMap.end()) sBulkFetchMap.clear();
1332
1333 if (folder_count > 0) 1417 if (folder_count > 0)
1334 { 1418 {
1335 sBulkFetchCount++; 1419 sBulkFetchCount++;
1336 1420 if (body["folders"].size())
1337 LLHTTPClient::post(url, body, new LLInventoryModel::fetchDescendentsResponder(body)); 1421 {
1422 LLHTTPClient::post(url, body, new fetchDescendentsResponder(body),300.0);
1423 }
1424 if (body_lib["folders"].size())
1425 {
1426 std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents");
1427 LLHTTPClient::post(url_lib, body_lib, new fetchDescendentsResponder(body_lib),300.0);
1428 }
1338 sFetchTimer.reset(); 1429 sFetchTimer.reset();
1339 } 1430 }
1340 1431 else if (isBulkFetchProcessingComplete())
1341 }
1342
1343 if (isBulkFetchProcessingComplete())
1344 { 1432 {
1345 if (sFullFetchStarted) 1433 if (sFullFetchStarted)
1346 { 1434 {
@@ -1391,6 +1479,14 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
1391} 1479}
1392 1480
1393//static 1481//static
1482void LLInventoryModel::findLostItems()
1483{
1484 sBackgroundFetchActive = TRUE;
1485 sFetchQueue.push_back(LLUUID::null);
1486 gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
1487}
1488
1489//static
1394void LLInventoryModel::stopBackgroundFetch() 1490void LLInventoryModel::stopBackgroundFetch()
1395{ 1491{
1396 if (sBackgroundFetchActive) 1492 if (sBackgroundFetchActive)
@@ -1409,14 +1505,7 @@ void LLInventoryModel::backgroundFetch(void*)
1409 if (sBackgroundFetchActive) 1505 if (sBackgroundFetchActive)
1410 { 1506 {
1411 //If we'll be using the capability, we'll be sending batches and the background thing isn't as important. 1507 //If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
1412 std::string url; 1508 std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");
1413
1414 LLViewerRegion * agent_region = gAgent.getRegion();
1415 if (agent_region)
1416 {
1417 url = agent_region->getCapability("FetchInventoryDescendents");
1418 }
1419
1420 if (!url.empty()) 1509 if (!url.empty())
1421 { 1510 {
1422 bulkFetch(url); 1511 bulkFetch(url);
@@ -3373,12 +3462,72 @@ bool LLInventoryFetchObserver::isEverythingComplete() const
3373 return mIncomplete.empty(); 3462 return mIncomplete.empty();
3374} 3463}
3375 3464
3465void fetch_items_from_llsd(const LLSD& items_llsd)
3466{
3467 if (!items_llsd.size()) return;
3468 LLSD body;
3469 body[0]["cap_name"] = "FetchInventory";
3470 body[1]["cap_name"] = "FetchLib";
3471 for (S32 i=0; i<items_llsd.size();i++)
3472 {
3473 if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString())
3474 {
3475 body[0]["items"].append(items_llsd[i]);
3476 continue;
3477 }
3478 if (items_llsd[i]["owner_id"].asString() == ALEXANDRIA_LINDEN_ID.asString())
3479 {
3480 body[1]["items"].append(items_llsd[i]);
3481 continue;
3482 }
3483 }
3484
3485 for (S32 i=0; i<body.size(); i++)
3486 {
3487 if (0 >= body[i].size()) continue;
3488 std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString());
3489
3490 if (!url.empty())
3491 {
3492 body[i]["agent_id"] = gAgent.getID();
3493 LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i]));
3494 break;
3495 }
3496
3497 LLMessageSystem* msg = gMessageSystem;
3498 BOOL start_new_message = TRUE;
3499 for (S32 j=0; j<body[i]["items"].size(); j++)
3500 {
3501 LLSD item_entry = body[i]["items"][j];
3502 if(start_new_message)
3503 {
3504 start_new_message = FALSE;
3505 msg->newMessageFast(_PREHASH_FetchInventory);
3506 msg->nextBlockFast(_PREHASH_AgentData);
3507 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
3508 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
3509 }
3510 msg->nextBlockFast(_PREHASH_InventoryData);
3511 msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID());
3512 msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID());
3513 if(msg->isSendFull(NULL))
3514 {
3515 start_new_message = TRUE;
3516 gAgent.sendReliableMessage();
3517 }
3518 }
3519 if(!start_new_message)
3520 {
3521 gAgent.sendReliableMessage();
3522 }
3523 }
3524}
3525
3376void LLInventoryFetchObserver::fetchItems( 3526void LLInventoryFetchObserver::fetchItems(
3377 const LLInventoryFetchObserver::item_ref_t& ids) 3527 const LLInventoryFetchObserver::item_ref_t& ids)
3378{ 3528{
3379 LLMessageSystem* msg = gMessageSystem;
3380 BOOL start_new_message = TRUE;
3381 LLUUID owner_id; 3529 LLUUID owner_id;
3530 LLSD items_llsd;
3382 for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it) 3531 for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it)
3383 { 3532 {
3384 LLViewerInventoryItem* item = gInventory.getItem(*it); 3533 LLViewerInventoryItem* item = gInventory.getItem(*it);
@@ -3400,31 +3549,18 @@ void LLInventoryFetchObserver::fetchItems(
3400 // assume it's agent inventory. 3549 // assume it's agent inventory.
3401 owner_id = gAgent.getID(); 3550 owner_id = gAgent.getID();
3402 } 3551 }
3403 3552
3404 // It's incomplete, so put it on the incomplete container, and 3553 // It's incomplete, so put it on the incomplete container, and
3405 // pack this on the message. 3554 // pack this on the message.
3406 mIncomplete.push_back(*it); 3555 mIncomplete.push_back(*it);
3407 if(start_new_message) 3556
3408 { 3557 // Prepare the data to fetch
3409 start_new_message = FALSE; 3558 LLSD item_entry;
3410 msg->newMessageFast(_PREHASH_FetchInventory); 3559 item_entry["owner_id"] = owner_id;
3411 msg->nextBlockFast(_PREHASH_AgentData); 3560 item_entry["item_id"] = (*it);
3412 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); 3561 items_llsd.append(item_entry);
3413 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
3414 }
3415 msg->nextBlockFast(_PREHASH_InventoryData);
3416 msg->addUUIDFast(_PREHASH_OwnerID, owner_id);
3417 msg->addUUIDFast(_PREHASH_ItemID, (*it));
3418 if(msg->isSendFull(NULL))
3419 {
3420 start_new_message = TRUE;
3421 gAgent.sendReliableMessage();
3422 }
3423 }
3424 if(!start_new_message)
3425 {
3426 gAgent.sendReliableMessage();
3427 } 3562 }
3563 fetch_items_from_llsd(items_llsd);
3428} 3564}
3429 3565
3430// virtual 3566// virtual
@@ -3579,9 +3715,8 @@ void LLInventoryFetchComboObserver::fetch(
3579 // descendent of an incomplete folder because the item will show 3715 // descendent of an incomplete folder because the item will show
3580 // up in an inventory descendents message soon enough so we do not 3716 // up in an inventory descendents message soon enough so we do not
3581 // have to fetch it individually. 3717 // have to fetch it individually.
3718 LLSD items_llsd;
3582 LLUUID owner_id; 3719 LLUUID owner_id;
3583 LLMessageSystem* msg = gMessageSystem;
3584 bool start_new_message = true;
3585 for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit) 3720 for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit)
3586 { 3721 {
3587 LLViewerInventoryItem* item = gInventory.getItem(*iit); 3722 LLViewerInventoryItem* item = gInventory.getItem(*iit);
@@ -3604,33 +3739,17 @@ void LLInventoryFetchComboObserver::fetch(
3604 } 3739 }
3605 if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end()) 3740 if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end())
3606 { 3741 {
3607 lldebugs << "fetching item " << *iit << llendl; 3742 LLSD item_entry;
3608 if(start_new_message) 3743 item_entry["owner_id"] = owner_id;
3609 { 3744 item_entry["item_id"] = (*iit);
3610 start_new_message = false; 3745 items_llsd.append(item_entry);
3611 msg->newMessageFast(_PREHASH_FetchInventory);
3612 msg->nextBlockFast(_PREHASH_AgentData);
3613 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
3614 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
3615 }
3616 msg->nextBlockFast(_PREHASH_InventoryData);
3617 msg->addUUIDFast(_PREHASH_OwnerID, owner_id);
3618 msg->addUUIDFast(_PREHASH_ItemID, (*iit));
3619 if(msg->isSendFullFast(_PREHASH_InventoryData))
3620 {
3621 start_new_message = true;
3622 gAgent.sendReliableMessage();
3623 }
3624 } 3746 }
3625 else 3747 else
3626 { 3748 {
3627 lldebugs << "not worrying about " << *iit << llendl; 3749 lldebugs << "not worrying about " << *iit << llendl;
3628 } 3750 }
3629 } 3751 }
3630 if(!start_new_message) 3752 fetch_items_from_llsd(items_llsd);
3631 {
3632 gAgent.sendReliableMessage();
3633 }
3634} 3753}
3635 3754
3636void LLInventoryExistenceObserver::watchItem(const LLUUID& id) 3755void LLInventoryExistenceObserver::watchItem(const LLUUID& id)
@@ -3676,7 +3795,17 @@ void LLInventoryAddedObserver::changed(U32 mask)
3676 // the network, figure out which item was updated. 3795 // the network, figure out which item was updated.
3677 // Code from Gigs Taggert, sin allowed by JC. 3796 // Code from Gigs Taggert, sin allowed by JC.
3678 LLMessageSystem* msg = gMessageSystem; 3797 LLMessageSystem* msg = gMessageSystem;
3679 std::string msg_name = msg->getMessageName(); 3798
3799 std::string msg_name;
3800 if (mMessageName.empty())
3801 {
3802 msg_name = msg->getMessageName();
3803 }
3804 else
3805 {
3806 msg_name = mMessageName;
3807 }
3808
3680 if (msg_name.empty()) 3809 if (msg_name.empty())
3681 { 3810 {
3682 return; 3811 return;