aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llinventorymodel.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-12-01 17:39:58 -0600
committerJacek Antonelli2008-12-01 17:40:06 -0600
commit7abecb48babe6a6f09bf6692ba55076546cfced9 (patch)
tree8d18a88513fb97adf32c10aae78f4be1984942db /linden/indra/newview/llinventorymodel.cpp
parentSecond Life viewer sources 1.21.6 (diff)
downloadmeta-impy-7abecb48babe6a6f09bf6692ba55076546cfced9.zip
meta-impy-7abecb48babe6a6f09bf6692ba55076546cfced9.tar.gz
meta-impy-7abecb48babe6a6f09bf6692ba55076546cfced9.tar.bz2
meta-impy-7abecb48babe6a6f09bf6692ba55076546cfced9.tar.xz
Second Life viewer sources 1.22.0-RC
Diffstat (limited to 'linden/indra/newview/llinventorymodel.cpp')
-rw-r--r--linden/indra/newview/llinventorymodel.cpp536
1 files changed, 331 insertions, 205 deletions
diff --git a/linden/indra/newview/llinventorymodel.cpp b/linden/indra/newview/llinventorymodel.cpp
index b1e3017..c3392ce 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
@@ -1259,88 +1348,84 @@ void LLInventoryModel::bulkFetch(std::string url)
1259 return; // just bail if we are disconnected. 1348 return; // just bail if we are disconnected.
1260 } 1349 }
1261 1350
1262 //HACK. This is inelegant. We're shuffling a dequeue to a map to get rid of
1263 //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.
1265 U32 folder_count=0; 1351 U32 folder_count=0;
1266 U32 max_batch_size=10; 1352 U32 max_batch_size=5;
1267 while( !(sFetchQueue.empty() ) ) 1353
1268 { 1354 U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1;
1269 LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front()); 1355
1270 1356 LLSD body;
1271 if (cat) 1357 LLSD body_lib;
1272 { 1358 while( !(sFetchQueue.empty() ) && (folder_count < max_batch_size) )
1273 if ( !gInventory.isCategoryComplete(cat->getUUID()) ) //grab this folder. 1359 {
1274 { 1360 if (sFetchQueue.front().isNull()) //DEV-17797
1275 sBulkFetchMap[(cat->getUUID())] = cat; 1361 {
1276 } 1362 LLSD folder_sd;
1277 else if (sFullFetchStarted) 1363 folder_sd["folder_id"] = LLUUID::null.asString();
1278 { //Already have this folder but append child folders to list. 1364 folder_sd["owner_id"] = gAgent.getID();
1279 // add all children to queue 1365 folder_sd["sort_order"] = (LLSD::Integer)sort_order;
1280 parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID()); 1366 folder_sd["fetch_folders"] = (LLSD::Boolean)FALSE;
1281 if (cat_it != gInventory.mParentChildCategoryTree.end()) 1367 folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
1282 { 1368 body["folders"].append(folder_sd);
1283 cat_array_t* child_categories = cat_it->second; 1369 folder_count++;
1284 1370 }
1285 for (S32 child_num = 0; child_num < child_categories->count(); child_num++) 1371 else
1286 { 1372 {
1287 sFetchQueue.push_back(child_categories->get(child_num)->getUUID()); 1373
1288 }
1289 }
1290 1374
1291 } 1375 LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front());
1292 } 1376
1377 if (cat)
1378 {
1379 if ( LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
1380 {
1381 LLSD folder_sd;
1382 folder_sd["folder_id"] = cat->getUUID();
1383 folder_sd["owner_id"] = cat->getOwnerID();
1384 folder_sd["sort_order"] = (LLSD::Integer)sort_order;
1385 folder_sd["fetch_folders"] = TRUE; //(LLSD::Boolean)sFullFetchStarted;
1386 folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
1387
1388 if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
1389 body_lib["folders"].append(folder_sd);
1390 else
1391 body["folders"].append(folder_sd);
1392 folder_count++;
1393 }
1394 if (sFullFetchStarted)
1395 { //Already have this folder but append child folders to list.
1396 // add all children to queue
1397 parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID());
1398 if (cat_it != gInventory.mParentChildCategoryTree.end())
1399 {
1400 cat_array_t* child_categories = cat_it->second;
1401
1402 for (S32 child_num = 0; child_num < child_categories->count(); child_num++)
1403 {
1404 sFetchQueue.push_back(child_categories->get(child_num)->getUUID());
1405 }
1406 }
1407
1408 }
1409 }
1410 }
1293 sFetchQueue.pop_front(); 1411 sFetchQueue.pop_front();
1294 } 1412 }
1295 1413
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) 1414 if (folder_count > 0)
1334 { 1415 {
1335 sBulkFetchCount++; 1416 sBulkFetchCount++;
1336 1417 if (body["folders"].size())
1337 LLHTTPClient::post(url, body, new LLInventoryModel::fetchDescendentsResponder(body)); 1418 {
1419 LLHTTPClient::post(url, body, new fetchDescendentsResponder(body),300.0);
1420 }
1421 if (body_lib["folders"].size())
1422 {
1423 std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents");
1424 LLHTTPClient::post(url_lib, body_lib, new fetchDescendentsResponder(body_lib),300.0);
1425 }
1338 sFetchTimer.reset(); 1426 sFetchTimer.reset();
1339 } 1427 }
1340 1428 else if (isBulkFetchProcessingComplete())
1341 }
1342
1343 if (isBulkFetchProcessingComplete())
1344 { 1429 {
1345 if (sFullFetchStarted) 1430 if (sFullFetchStarted)
1346 { 1431 {
@@ -1391,6 +1476,14 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
1391} 1476}
1392 1477
1393//static 1478//static
1479void LLInventoryModel::findLostItems()
1480{
1481 sBackgroundFetchActive = TRUE;
1482 sFetchQueue.push_back(LLUUID::null);
1483 gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
1484}
1485
1486//static
1394void LLInventoryModel::stopBackgroundFetch() 1487void LLInventoryModel::stopBackgroundFetch()
1395{ 1488{
1396 if (sBackgroundFetchActive) 1489 if (sBackgroundFetchActive)
@@ -1409,14 +1502,7 @@ void LLInventoryModel::backgroundFetch(void*)
1409 if (sBackgroundFetchActive) 1502 if (sBackgroundFetchActive)
1410 { 1503 {
1411 //If we'll be using the capability, we'll be sending batches and the background thing isn't as important. 1504 //If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
1412 std::string url; 1505 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()) 1506 if (!url.empty())
1421 { 1507 {
1422 bulkFetch(url); 1508 bulkFetch(url);
@@ -3373,12 +3459,72 @@ bool LLInventoryFetchObserver::isEverythingComplete() const
3373 return mIncomplete.empty(); 3459 return mIncomplete.empty();
3374} 3460}
3375 3461
3462void fetch_items_from_llsd(const LLSD& items_llsd)
3463{
3464 if (!items_llsd.size()) return;
3465 LLSD body;
3466 body[0]["cap_name"] = "FetchInventory";
3467 body[1]["cap_name"] = "FetchLib";
3468 for (S32 i=0; i<items_llsd.size();i++)
3469 {
3470 if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString())
3471 {
3472 body[0]["items"].append(items_llsd[i]);
3473 continue;
3474 }
3475 if (items_llsd[i]["owner_id"].asString() == ALEXANDRIA_LINDEN_ID.asString())
3476 {
3477 body[1]["items"].append(items_llsd[i]);
3478 continue;
3479 }
3480 }
3481
3482 for (S32 i=0; i<body.size(); i++)
3483 {
3484 if (0 >= body[i].size()) continue;
3485 std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString());
3486
3487 if (!url.empty())
3488 {
3489 body[i]["agent_id"] = gAgent.getID();
3490 LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i]));
3491 break;
3492 }
3493
3494 LLMessageSystem* msg = gMessageSystem;
3495 BOOL start_new_message = TRUE;
3496 for (S32 j=0; j<body[i]["items"].size(); j++)
3497 {
3498 LLSD item_entry = body[i]["items"][j];
3499 if(start_new_message)
3500 {
3501 start_new_message = FALSE;
3502 msg->newMessageFast(_PREHASH_FetchInventory);
3503 msg->nextBlockFast(_PREHASH_AgentData);
3504 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
3505 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
3506 }
3507 msg->nextBlockFast(_PREHASH_InventoryData);
3508 msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID());
3509 msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID());
3510 if(msg->isSendFull(NULL))
3511 {
3512 start_new_message = TRUE;
3513 gAgent.sendReliableMessage();
3514 }
3515 }
3516 if(!start_new_message)
3517 {
3518 gAgent.sendReliableMessage();
3519 }
3520 }
3521}
3522
3376void LLInventoryFetchObserver::fetchItems( 3523void LLInventoryFetchObserver::fetchItems(
3377 const LLInventoryFetchObserver::item_ref_t& ids) 3524 const LLInventoryFetchObserver::item_ref_t& ids)
3378{ 3525{
3379 LLMessageSystem* msg = gMessageSystem;
3380 BOOL start_new_message = TRUE;
3381 LLUUID owner_id; 3526 LLUUID owner_id;
3527 LLSD items_llsd;
3382 for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it) 3528 for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it)
3383 { 3529 {
3384 LLViewerInventoryItem* item = gInventory.getItem(*it); 3530 LLViewerInventoryItem* item = gInventory.getItem(*it);
@@ -3400,31 +3546,18 @@ void LLInventoryFetchObserver::fetchItems(
3400 // assume it's agent inventory. 3546 // assume it's agent inventory.
3401 owner_id = gAgent.getID(); 3547 owner_id = gAgent.getID();
3402 } 3548 }
3403 3549
3404 // It's incomplete, so put it on the incomplete container, and 3550 // It's incomplete, so put it on the incomplete container, and
3405 // pack this on the message. 3551 // pack this on the message.
3406 mIncomplete.push_back(*it); 3552 mIncomplete.push_back(*it);
3407 if(start_new_message) 3553
3408 { 3554 // Prepare the data to fetch
3409 start_new_message = FALSE; 3555 LLSD item_entry;
3410 msg->newMessageFast(_PREHASH_FetchInventory); 3556 item_entry["owner_id"] = owner_id;
3411 msg->nextBlockFast(_PREHASH_AgentData); 3557 item_entry["item_id"] = (*it);
3412 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); 3558 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 } 3559 }
3560 fetch_items_from_llsd(items_llsd);
3428} 3561}
3429 3562
3430// virtual 3563// virtual
@@ -3579,9 +3712,8 @@ void LLInventoryFetchComboObserver::fetch(
3579 // descendent of an incomplete folder because the item will show 3712 // descendent of an incomplete folder because the item will show
3580 // up in an inventory descendents message soon enough so we do not 3713 // up in an inventory descendents message soon enough so we do not
3581 // have to fetch it individually. 3714 // have to fetch it individually.
3715 LLSD items_llsd;
3582 LLUUID owner_id; 3716 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) 3717 for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit)
3586 { 3718 {
3587 LLViewerInventoryItem* item = gInventory.getItem(*iit); 3719 LLViewerInventoryItem* item = gInventory.getItem(*iit);
@@ -3604,33 +3736,17 @@ void LLInventoryFetchComboObserver::fetch(
3604 } 3736 }
3605 if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end()) 3737 if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end())
3606 { 3738 {
3607 lldebugs << "fetching item " << *iit << llendl; 3739 LLSD item_entry;
3608 if(start_new_message) 3740 item_entry["owner_id"] = owner_id;
3609 { 3741 item_entry["item_id"] = (*iit);
3610 start_new_message = false; 3742 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 } 3743 }
3625 else 3744 else
3626 { 3745 {
3627 lldebugs << "not worrying about " << *iit << llendl; 3746 lldebugs << "not worrying about " << *iit << llendl;
3628 } 3747 }
3629 } 3748 }
3630 if(!start_new_message) 3749 fetch_items_from_llsd(items_llsd);
3631 {
3632 gAgent.sendReliableMessage();
3633 }
3634} 3750}
3635 3751
3636void LLInventoryExistenceObserver::watchItem(const LLUUID& id) 3752void LLInventoryExistenceObserver::watchItem(const LLUUID& id)
@@ -3676,7 +3792,17 @@ void LLInventoryAddedObserver::changed(U32 mask)
3676 // the network, figure out which item was updated. 3792 // the network, figure out which item was updated.
3677 // Code from Gigs Taggert, sin allowed by JC. 3793 // Code from Gigs Taggert, sin allowed by JC.
3678 LLMessageSystem* msg = gMessageSystem; 3794 LLMessageSystem* msg = gMessageSystem;
3679 std::string msg_name = msg->getMessageName(); 3795
3796 std::string msg_name;
3797 if (mMessageName.empty())
3798 {
3799 msg_name = msg->getMessageName();
3800 }
3801 else
3802 {
3803 msg_name = mMessageName;
3804 }
3805
3680 if (msg_name.empty()) 3806 if (msg_name.empty())
3681 { 3807 {
3682 return; 3808 return;