diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index f45237a73ca1c92350708ef15ee076321051ab96..5c7e9c8db2af94c3ee76b8af31d6b923c61bd92e 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -253,6 +253,7 @@ set(viewer_SOURCE_FILES
     llinventoryfilter.cpp
     llinventoryfunctions.cpp
     llinventorymodel.cpp
+    llinventorymodelbackgroundfetch.cpp
     llinventoryobserver.cpp
     llinventorypanel.cpp
     lljoystickbutton.cpp
@@ -754,6 +755,7 @@ set(viewer_HEADER_FILES
     llinventoryfilter.h
     llinventoryfunctions.h
     llinventorymodel.h
+    llinventorymodelbackgroundfetch.h
     llinventoryobserver.h
     llinventorypanel.h
     lljoystickbutton.h
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 391e63f73004af0a6dbb248acf760cf5aa109947..f05bd8574fbddc7d775ae24837bb058824ebf9cf 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -52,6 +52,7 @@
 #include "llfloaterreg.h"		// getTypedInstance()
 #include "llfocusmgr.h"
 #include "llinventorymodel.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llinventoryobserver.h"
 #include "lllandmarklist.h"
 #include "lllineeditor.h"
@@ -322,7 +323,7 @@ void LLFloaterWorldMap::onOpen(const LLSD& key)
 
 		// Start speculative download of landmarks
 		const LLUUID landmark_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
-		gInventory.startBackgroundFetch(landmark_folder_id);
+		LLInventoryModelBackgroundFetch::instance().start(landmark_folder_id);
 
 		childSetFocus("location", TRUE);
 		gFocusMgr.triggerFocusFlash();
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 149bbe805dfa64b032a2d3336b737386fbc4cded..4fbd1efbef42c0e3056f8c8b54012fed4a7cedac 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -39,6 +39,7 @@
 #include "llinventoryclipboard.h" // *TODO: remove this once hack below gone.
 #include "llinventoryfilter.h"
 #include "llinventoryfunctions.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llinventorypanel.h"
 #include "llfoldertype.h"
 #include "llfloaterinventory.h"// hacked in for the bonus context menu items.
@@ -943,7 +944,7 @@ void LLFolderView::draw()
 	}
 	else
 	{
-		if (gInventory.backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration())
+		if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration())
 		{
 			mStatusText = LLTrans::getString("Searching");
 			//font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL,  LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index bb4c75d3ac68d2a1455d377d1c315f5f5856cfef..ecbaac57434f9e2f32e68cca8914f9c4f70740d1 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -38,6 +38,7 @@
 #include "llfoldervieweventlistener.h"
 #include "llinventorybridge.h"	// for LLItemBridge in LLInventorySort::operator()
 #include "llinventoryfilter.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llpanel.h"
 #include "llviewercontrol.h"	// gSavedSettings
 #include "llviewerwindow.h"		// Argh, only for setCursor()
@@ -992,16 +993,16 @@ void LLFolderViewItem::draw()
 		if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(),gInventory.getRootFolderID()))
 		{
 			// Descendent of my inventory.
-			root_is_loading = gInventory.myInventoryFetchInProgress();
+			root_is_loading = LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress();
 		}
 		if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(),gInventory.getLibraryRootFolderID()))
 		{
 			// Descendent of library
-			root_is_loading = gInventory.libraryFetchInProgress();
+			root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress();
 		}
 			
 		if ( (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime"))
-			|| (LLInventoryModel::backgroundFetchActive() && root_is_loading && mShowLoadStatus) )
+			|| (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() && root_is_loading && mShowLoadStatus) )
 		{
 			std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) ";
 			font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor,
@@ -1317,7 +1318,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
 	// when applying a filter, matching folders get their contents downloaded first
 	if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && (mListener && !gInventory.isCategoryComplete(mListener->getUUID())))
 	{
-		gInventory.startBackgroundFetch(mListener->getUUID());
+		LLInventoryModelBackgroundFetch::instance().start(mListener->getUUID());
 	}
 
 	// now query children
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index efd23c36cabd737ded4f6c883ffa1fcf3c2687f5..899a70303ba3959d1ef71c498e4cd93e0cef6265 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -52,6 +52,7 @@
 #include "llinventoryclipboard.h"
 #include "llinventoryfunctions.h"
 #include "llinventorymodel.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llinventorypanel.h"
 #include "llnotifications.h"
 #include "llnotificationsutil.h"
@@ -729,7 +730,7 @@ BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
 
 		if (*type == DAD_CATEGORY)
 		{
-			gInventory.startBackgroundFetch(obj->getUUID());
+			LLInventoryModelBackgroundFetch::instance().start(obj->getUUID());
 		}
 
 		rv = TRUE;
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index cd20d64ca8ef9384f0c1785b7821a9654fd68510..1a488175ac93ef1c3c5d0f0a0a6bd0b3c2cdd83d 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -37,7 +37,8 @@
 // viewer includes
 #include "llfoldervieweventlistener.h"
 #include "llfolderviewitem.h"
-#include "llinventorymodel.h"	// gInventory.backgroundFetchActive()
+#include "llinventorymodel.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llviewercontrol.h"
 #include "llfolderview.h"
 
@@ -713,7 +714,7 @@ const std::string& LLInventoryFilter::getFilterText()
 		filtered_by_all_types = FALSE;
 	}
 
-	if (!gInventory.backgroundFetchActive()
+	if (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()
 		&& filtered_by_type
 		&& !filtered_by_all_types)
 	{
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 41f0b430e86f987894d3b345716ff42bc1f2d4af..96b9bbb725cf0b0b77c4114e98fd25487aaa6554 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -57,32 +57,16 @@
 #include "process.h"
 #endif
 
-BOOL LLInventoryModel::sBackgroundFetchActive = FALSE;
-BOOL LLInventoryModel::sAllFoldersFetched = FALSE;
-BOOL LLInventoryModel::sMyInventoryFetchStarted = FALSE;
-BOOL LLInventoryModel::sLibraryFetchStarted = FALSE;
-S32  LLInventoryModel::sNumFetchRetries = 0;
-F32  LLInventoryModel::sMinTimeBetweenFetches = 0.3f;
-F32  LLInventoryModel::sMaxTimeBetweenFetches = 10.f;
-BOOL LLInventoryModel::sTimelyFetchPending = FALSE;
-LLFrameTimer LLInventoryModel::sFetchTimer;
-S16 LLInventoryModel::sBulkFetchCount = 0;
-BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE;
-
 // Increment this if the inventory contents change in a non-backwards-compatible way.
 // For viewer 2, the addition of link items makes a pre-viewer-2 cache incorrect.
 const S32 LLInventoryModel::sCurrentInvCacheVersion = 2;
-
-// RN: for some reason, using std::queue in the header file confuses the compiler which things it's an xmlrpc_queue
-static std::deque<LLUUID> sFetchQueue;
+BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE;
 
 ///----------------------------------------------------------------------------
 /// Local function declarations, constants, enums, and typedefs
 ///----------------------------------------------------------------------------
 
 //BOOL decompress_file(const char* src_filename, const char* dst_filename);
-const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;
-const S32 MAX_FETCH_RETRIES = 10;
 const char CACHE_FORMAT_STRING[] = "%s.inv"; 
 
 struct InventoryIDPtrLess
@@ -1345,542 +1329,6 @@ bool LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id)
 	return cat->fetchDescendents();
 }
 
-//Initialize statics.
-bool LLInventoryModel::isBulkFetchProcessingComplete()
-{
-	return sFetchQueue.empty() && sBulkFetchCount<=0;
-}
-
-class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
-{
-	public:
-		LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
-		//LLInventoryModelFetchDescendentsResponder() {};
-		void result(const LLSD& content);
-		void error(U32 status, const std::string& reason);
-	public:
-		typedef std::vector<LLViewerInventoryCategory*> folder_ref_t;
-	protected:
-		LLSD mRequestSD;
-};
-
-//If we get back a normal response, handle it here
-void  LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)
-{
-	if (content.has("folders"))	
-	{
-
-		for(LLSD::array_const_iterator folder_it = content["folders"].beginArray();
-			folder_it != content["folders"].endArray();
-			++folder_it)
-		{	
-			LLSD folder_sd = *folder_it;
-			
-
-			//LLUUID agent_id = folder_sd["agent_id"];
-
-			//if(agent_id != gAgent.getID())	//This should never happen.
-			//{
-			//	llwarns << "Got a UpdateInventoryItem for the wrong agent."
-			//			<< llendl;
-			//	break;
-			//}
-
-			LLUUID parent_id = folder_sd["folder_id"];
-			LLUUID owner_id = folder_sd["owner_id"];
-			S32    version  = (S32)folder_sd["version"].asInteger();
-			S32    descendents = (S32)folder_sd["descendents"].asInteger();
-			LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id);
-
-            if (parent_id.isNull())
-            {
-			    LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
-			    for(LLSD::array_const_iterator item_it = folder_sd["items"].beginArray();
-				    item_it != folder_sd["items"].endArray();
-				    ++item_it)
-			    {	
-                    const LLUUID lost_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
-                    if (lost_uuid.notNull())
-                    {
-				        LLSD item = *item_it;
-				        titem->unpackMessage(item);
-				
-                        LLInventoryModel::update_list_t update;
-                        LLInventoryModel::LLCategoryUpdate new_folder(lost_uuid, 1);
-                        update.push_back(new_folder);
-                        gInventory.accountForUpdate(update);
-
-                        titem->setParent(lost_uuid);
-                        titem->updateParentOnServer(FALSE);
-                        gInventory.updateItem(titem);
-                        gInventory.notifyObservers("fetchDescendents");
-                        
-                    }
-                }
-            }
-
-	        LLViewerInventoryCategory* pcat = gInventory.getCategory(parent_id);
-			if (!pcat)
-			{
-				continue;
-			}
-
-			for(LLSD::array_const_iterator category_it = folder_sd["categories"].beginArray();
-				category_it != folder_sd["categories"].endArray();
-				++category_it)
-			{	
-				LLSD category = *category_it;
-				tcategory->fromLLSD(category); 
-							
-				if (LLInventoryModel::sMyInventoryFetchStarted ||
-					LLInventoryModel::sLibraryFetchStarted)
-				{
-					sFetchQueue.push_back(tcategory->getUUID());
-				}
-				else if ( !gInventory.isCategoryComplete(tcategory->getUUID()) )
-				{
-					gInventory.updateCategory(tcategory);
-				}
-
-			}
-			LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
-			for(LLSD::array_const_iterator item_it = folder_sd["items"].beginArray();
-				item_it != folder_sd["items"].endArray();
-				++item_it)
-			{	
-				LLSD item = *item_it;
-				titem->unpackMessage(item);
-				
-				gInventory.updateItem(titem);
-			}
-
-			// set version and descendentcount according to message.
-			LLViewerInventoryCategory* cat = gInventory.getCategory(parent_id);
-			if(cat)
-			{
-				cat->setVersion(version);
-				cat->setDescendentCount(descendents);
-				cat->determineFolderType();
-			}
-
-		}
-	}
-		
-	if (content.has("bad_folders"))
-	{
-		for(LLSD::array_const_iterator folder_it = content["bad_folders"].beginArray();
-			folder_it != content["bad_folders"].endArray();
-			++folder_it)
-		{	
-			LLSD folder_sd = *folder_it;
-			
-			//These folders failed on the dataserver.  We probably don't want to retry them.
-			llinfos << "Folder " << folder_sd["folder_id"].asString() 
-					<< "Error: " << folder_sd["error"].asString() << llendl;
-		}
-	}
-
-	LLInventoryModel::incrBulkFetch(-1);
-	
-	if (LLInventoryModel::isBulkFetchProcessingComplete())
-	{
-		llinfos << "Inventory fetch completed" << llendl;
-		LLInventoryModel::setAllFoldersFetched();
-	}
-	
-	gInventory.notifyObservers("fetchDescendents");
-}
-
-//If we get back an error (not found, etc...), handle it here
-void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::string& reason)
-{
-	llinfos << "LLInventoryModelFetchDescendentsResponder::error "
-		<< status << ": " << reason << llendl;
-						
-	LLInventoryModel::incrBulkFetch(-1);
-
-	if (status==499)		//timed out.  Let's be awesome!
-	{
-		for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray();
-			folder_it != mRequestSD["folders"].endArray();
-			++folder_it)
-		{	
-			LLSD folder_sd = *folder_it;
-			LLUUID folder_id = folder_sd["folder_id"];
-			sFetchQueue.push_front(folder_id);
-		}
-	}
-	else
-	{
-		if (LLInventoryModel::isBulkFetchProcessingComplete())
-		{
-			LLInventoryModel::setAllFoldersFetched();
-		}
-	}
-	gInventory.notifyObservers("fetchDescendents");
-}
-
-//static   Bundle up a bunch of requests to send all at once.
-void LLInventoryModel::bulkFetch(std::string url)
-{
-	//Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped.
-	//If there are items in sFetchQueue, we want to check the time since the last bulkFetch was 
-	//sent.  If it exceeds our retry time, go ahead and fire off another batch.  
-	//Stopbackgroundfetch will be run from the Responder instead of here.  
-
-	S16 max_concurrent_fetches=8;
-	F32 new_min_time = 0.5f;			//HACK!  Clean this up when old code goes away entirely.
-	if (sMinTimeBetweenFetches < new_min_time) sMinTimeBetweenFetches=new_min_time;  //HACK!  See above.
-	
-	if(gDisconnected 
-	|| sBulkFetchCount > max_concurrent_fetches
-	|| sFetchTimer.getElapsedTimeF32() < sMinTimeBetweenFetches)
-	{
-		return; // just bail if we are disconnected.
-	}	
-
-	U32 folder_count=0;
-	U32 max_batch_size=5;
-
-	U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER) & 0x1;
-
-	LLSD body;
-	LLSD body_lib;
-	while( !(sFetchQueue.empty() ) && (folder_count < max_batch_size) )
-	{
-        if (sFetchQueue.front().isNull()) //DEV-17797
-        {
-			LLSD folder_sd;
-			folder_sd["folder_id"]		= LLUUID::null.asString();
-			folder_sd["owner_id"]		= gAgent.getID();
-			folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
-			folder_sd["fetch_folders"]	= (LLSD::Boolean)FALSE;
-			folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
-			body["folders"].append(folder_sd);
-            folder_count++;
-        }
-        else
-        {
-				
-
-		    LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front());
-		
-		    if (cat)
-		    {
-			    if ( LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
-			    {
-				    LLSD folder_sd;
-				    folder_sd["folder_id"]		= cat->getUUID();
-				    folder_sd["owner_id"]		= cat->getOwnerID();
-				    folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
-				    folder_sd["fetch_folders"]	= TRUE; //(LLSD::Boolean)sFullFetchStarted;
-				    folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
-				    
-				    if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
-					    body_lib["folders"].append(folder_sd);
-				    else
-					    body["folders"].append(folder_sd);
-				    folder_count++;
-			    }
-			    if (sMyInventoryFetchStarted ||
-					sLibraryFetchStarted)
-			    {	//Already have this folder but append child folders to list.
-				    // add all children to queue
-				    parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID());
-				    if (cat_it != gInventory.mParentChildCategoryTree.end())
-				    {
-					    cat_array_t* child_categories = cat_it->second;
-    
-					    for (S32 child_num = 0; child_num < child_categories->count(); child_num++)
-					    {
-						    sFetchQueue.push_back(child_categories->get(child_num)->getUUID());
-					    }
-				    }
-    
-			    }
-		    }
-        }
-		sFetchQueue.pop_front();
-	}
-		
-		if (folder_count > 0)
-		{
-			sBulkFetchCount++;
-			if (body["folders"].size())
-			{
-				LLHTTPClient::post(url, body, new LLInventoryModelFetchDescendentsResponder(body),300.0);
-			}
-			if (body_lib["folders"].size())
-			{
-				std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents");
-				LLHTTPClient::post(url_lib, body_lib, new LLInventoryModelFetchDescendentsResponder(body_lib),300.0);
-			}
-			sFetchTimer.reset();
-		}
-	else if (isBulkFetchProcessingComplete())
-	{
-		setAllFoldersFetched();
-	}	
-}
-
-bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id)
-{
-	for (std::deque<LLUUID>::iterator it = sFetchQueue.begin();
-		 it != sFetchQueue.end(); ++it)
-	{
-		const LLUUID& fetch_id = *it;
-		if (gInventory.isObjectDescendentOf(fetch_id, cat_id))
-			return false;
-	}
-	return true;
-}
-
-/* static */
-bool LLInventoryModel::libraryFetchStarted()
-{
-	return sLibraryFetchStarted;
-}
-
-/* static */
-bool LLInventoryModel::libraryFetchCompleted()
-{
-	return libraryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getLibraryRootFolderID());
-}
-
-/* static */
-bool LLInventoryModel::libraryFetchInProgress()
-{
-	return libraryFetchStarted() && !libraryFetchCompleted();
-}
-	
-/* static */
-bool LLInventoryModel::myInventoryFetchStarted()
-{
-	return sMyInventoryFetchStarted;
-}
-
-/* static */
-bool LLInventoryModel::myInventoryFetchCompleted()
-{
-	return myInventoryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getRootFolderID());
-}
-
-/* static */
-bool LLInventoryModel::myInventoryFetchInProgress()
-{
-	return myInventoryFetchStarted() && !myInventoryFetchCompleted();
-}
-
-// static
-bool LLInventoryModel::isEverythingFetched()
-{
-	return sAllFoldersFetched;
-}
-
-//static
-BOOL LLInventoryModel::backgroundFetchActive()
-{
-	return sBackgroundFetchActive;
-}
-
-void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
-{
-	if (!sAllFoldersFetched)
-	{
-		sBackgroundFetchActive = TRUE;
-		if (cat_id.isNull())
-		{
-			if (!sMyInventoryFetchStarted)
-			{
-				sMyInventoryFetchStarted = TRUE;
-				sFetchQueue.push_back(gInventory.getRootFolderID());
-				gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
-			}
-			if (!sLibraryFetchStarted)
-			{
-				sLibraryFetchStarted = TRUE;
-				sFetchQueue.push_back(gInventory.getLibraryRootFolderID());
-				gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
-			}
-		}
-		else
-		{
-			// specific folder requests go to front of queue
-			if (sFetchQueue.empty() || sFetchQueue.front() != cat_id)
-			{
-				sFetchQueue.push_front(cat_id);
-				gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
-			}
-			if (cat_id == gInventory.getLibraryRootFolderID())
-			{
-				sLibraryFetchStarted = TRUE;
-			}
-			if (cat_id == gInventory.getRootFolderID())
-			{
-				sMyInventoryFetchStarted = TRUE;
-			}
-		}
-	}
-}
-
-//static
-void LLInventoryModel::findLostItems()
-{
-	sBackgroundFetchActive = TRUE;
-    sFetchQueue.push_back(LLUUID::null);
-    gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
-}
-
-//static
-void LLInventoryModel::stopBackgroundFetch()
-{
-	if (sBackgroundFetchActive)
-	{
-		sBackgroundFetchActive = FALSE;
-		gIdleCallbacks.deleteFunction(&LLInventoryModel::backgroundFetch, NULL);
-		sBulkFetchCount=0;
-		sMinTimeBetweenFetches=0.0f;
-	}
-}
-
-// static
-void LLInventoryModel::setAllFoldersFetched()
-{
-	if (sMyInventoryFetchStarted &&
-		sLibraryFetchStarted)
-	{
-		sAllFoldersFetched = TRUE;
-	}
-	stopBackgroundFetch();
-}
-
-//static 
-void LLInventoryModel::backgroundFetch(void*)
-{
-	if (sBackgroundFetchActive && gAgent.getRegion())
-	{
-		//If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
-		std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");   
-		if (!url.empty()) 
-		{
-			bulkFetch(url);
-			return;
-		}
-		
-		//DEPRECATED OLD CODE FOLLOWS.
-		// no more categories to fetch, stop fetch process
-		if (sFetchQueue.empty())
-		{
-			llinfos << "Inventory fetch completed" << llendl;
-
-			setAllFoldersFetched();
-			return;
-		}
-
-		F32 fast_fetch_time = lerp(sMinTimeBetweenFetches, sMaxTimeBetweenFetches, 0.1f);
-		F32 slow_fetch_time = lerp(sMinTimeBetweenFetches, sMaxTimeBetweenFetches, 0.5f);
-		if (sTimelyFetchPending && sFetchTimer.getElapsedTimeF32() > slow_fetch_time)
-		{
-			// double timeouts on failure
-			sMinTimeBetweenFetches = llmin(sMinTimeBetweenFetches * 2.f, 10.f);
-			sMaxTimeBetweenFetches = llmin(sMaxTimeBetweenFetches * 2.f, 120.f);
-			llinfos << "Inventory fetch times grown to (" << sMinTimeBetweenFetches << ", " << sMaxTimeBetweenFetches << ")" << llendl;
-			// fetch is no longer considered "timely" although we will wait for full time-out
-			sTimelyFetchPending = FALSE;
-		}
-
-		while(1)
-		{
-			if (sFetchQueue.empty())
-			{
-				break;
-			}
-
-			if(gDisconnected)
-			{
-				// just bail if we are disconnected.
-				break;
-			}
-
-			LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front());
-
-			// category has been deleted, remove from queue.
-			if (!cat)
-			{
-				sFetchQueue.pop_front();
-				continue;
-			}
-			
-			if (sFetchTimer.getElapsedTimeF32() > sMinTimeBetweenFetches && 
-				LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
-			{
-				// category exists but has no children yet, fetch the descendants
-				// for now, just request every time and rely on retry timer to throttle
-				if (cat->fetchDescendents())
-				{
-					sFetchTimer.reset();
-					sTimelyFetchPending = TRUE;
-				}
-				else
-				{
-					//  The catagory also tracks if it has expired and here it says it hasn't
-					//  yet.  Get out of here because nothing is going to happen until we
-					//  update the timers.
-					break;
-				}
-			}
-			// do I have all my children?
-			else if (gInventory.isCategoryComplete(sFetchQueue.front()))
-			{
-				// finished with this category, remove from queue
-				sFetchQueue.pop_front();
-
-				// add all children to queue
-				parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID());
-				if (cat_it != gInventory.mParentChildCategoryTree.end())
-				{
-					cat_array_t* child_categories = cat_it->second;
-
-					for (S32 child_num = 0; child_num < child_categories->count(); child_num++)
-					{
-						sFetchQueue.push_back(child_categories->get(child_num)->getUUID());
-					}
-				}
-
-				// we received a response in less than the fast time
-				if (sTimelyFetchPending && sFetchTimer.getElapsedTimeF32() < fast_fetch_time)
-				{
-					// shrink timeouts based on success
-					sMinTimeBetweenFetches = llmax(sMinTimeBetweenFetches * 0.8f, 0.3f);
-					sMaxTimeBetweenFetches = llmax(sMaxTimeBetweenFetches * 0.8f, 10.f);
-					//llinfos << "Inventory fetch times shrunk to (" << sMinTimeBetweenFetches << ", " << sMaxTimeBetweenFetches << ")" << llendl;
-				}
-
-				sTimelyFetchPending = FALSE;
-				continue;
-			}
-			else if (sFetchTimer.getElapsedTimeF32() > sMaxTimeBetweenFetches)
-			{
-				// received first packet, but our num descendants does not match db's num descendants
-				// so try again later
-				LLUUID fetch_id = sFetchQueue.front();
-				sFetchQueue.pop_front();
-
-				if (sNumFetchRetries++ < MAX_FETCH_RETRIES)
-				{
-					// push on back of queue
-					sFetchQueue.push_back(fetch_id);
-				}
-				sTimelyFetchPending = FALSE;
-				sFetchTimer.reset();
-				break;
-			}
-
-			// not enough time has elapsed to do a new fetch
-			break;
-		}
-	}
-}
 
 void LLInventoryModel::cache(
 	const LLUUID& parent_folder_id,
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 2a2b48ce3c620d736dffee7b837b9cbe4b9f5b06..700e5317f77d9a00e693701a967bdcbc6d057da2 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -81,7 +81,6 @@ class LLInventoryModel
 		CHILDREN_MAYBE
 	};
 
-	// These are used a lot...
 	typedef LLDynamicArray<LLPointer<LLViewerInventoryCategory> > cat_array_t;
 	typedef LLDynamicArray<LLPointer<LLViewerInventoryItem> > item_array_t;
 	typedef std::set<LLUUID> changed_items_t;
@@ -368,8 +367,6 @@ class LLInventoryModel
 	// Utility Functions
 	void removeItem(const LLUUID& item_id);
 	
-    static void findLostItems();
-
 	// Data about the agent's root folder and root library folder
 	// are stored here, rather than in LLAgent where it used to be, because
 	// gInventory is a singleton and represents the agent's inventory.
@@ -501,12 +498,6 @@ class LLInventoryModel
 	LLUUID mLibraryRootFolderID;
 	LLUUID mLibraryOwnerID;
 
-	static BOOL sTimelyFetchPending;
-	static S32  sNumFetchRetries;
-	static LLFrameTimer sFetchTimer;
-	static F32 sMinTimeBetweenFetches;
-	static F32 sMaxTimeBetweenFetches;
-
 	// Expected inventory cache version
 	const static S32 sCurrentInvCacheVersion;
 	
@@ -532,41 +523,6 @@ class LLInventoryModel
 	// *NOTE: DEBUG functionality
 	void dumpInventory() const;
 
-
-	////////////////////////////////////////////////////////////////////////////////
-	// Bulk fetch
-public:
-	// Start and stop background breadth-first fetching of inventory contents.
-	// This gets triggered when performing a filter-search
-	void startBackgroundFetch(const LLUUID& cat_id = LLUUID::null);
-	static BOOL backgroundFetchActive();
-	static bool isEverythingFetched();
-	static void backgroundFetch(void*); // background fetch idle function
-	static void incrBulkFetch(S16 fetching) {  sBulkFetchCount+=fetching; if (sBulkFetchCount<0) sBulkFetchCount=0; }
-	static void stopBackgroundFetch(); // stop fetch process
-	static bool isBulkFetchProcessingComplete();
-
-	// Add categories to a list to be fetched in bulk.
-	static void bulkFetch(std::string url);
-
-	static bool libraryFetchStarted();
-	static bool libraryFetchCompleted();
-	static bool libraryFetchInProgress();
-	
-	static bool myInventoryFetchStarted();
-	static bool myInventoryFetchCompleted();
-	static bool myInventoryFetchInProgress();
-	
-private:
- 	static BOOL sMyInventoryFetchStarted;
-	static BOOL sLibraryFetchStarted;
-	static BOOL sAllFoldersFetched; 
-	static void setAllFoldersFetched();
-
-	// completing the fetch once per session should be sufficient
-	static BOOL sBackgroundFetchActive;
-	static S16 sBulkFetchCount;
-
 	////////////////////////////////////////////////////////////////////////////////
 	// Login status
 public:
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 9a2d76e7e2e96f8be6d51334b3bbc9c12f05ef23..f38659ba5f4c00f73bc5943a6df2dc69958a0325 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -43,6 +43,7 @@
 #include "llimfloater.h"
 #include "llimview.h"
 #include "llinventorybridge.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llsidepanelinventory.h"
 #include "llsidetray.h"
 #include "llscrollcontainer.h"
@@ -643,7 +644,7 @@ BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask)
 	if(handled)
 	{
 		ECursorType cursor = getWindow()->getCursor();
-		if (LLInventoryModel::backgroundFetchActive() && cursor == UI_CURSOR_ARROW)
+		if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() && cursor == UI_CURSOR_ARROW)
 		{
 			// replace arrow cursor with arrow and hourglass cursor
 			getWindow()->setCursor(UI_CURSOR_WORKING);
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index e3b8581acaa154b9b5ce152e46bba3828cc0dbf0..4cde02c1ce15130ea4542f7c425a48ab98d0a210 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -49,6 +49,7 @@
 #include "lldndbutton.h"
 #include "llfloaterworldmap.h"
 #include "llfolderviewitem.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llinventorypanel.h"
 #include "lllandmarkactions.h"
 #include "llplacesinventorybridge.h"
@@ -556,7 +557,7 @@ void LLLandmarksPanel::initLibraryInventoryPanel()
 	const LLUUID &landmarks_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false, true);
 	if (landmarks_cat.notNull())
 	{
-		gInventory.startBackgroundFetch(landmarks_cat);
+		LLInventoryModelBackgroundFetch::instance().start(landmarks_cat);
 	}
 
 	// Expanding "Library" tab for new users who have no landmarks in "My Inventory".
@@ -620,7 +621,7 @@ void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesI
 		  if (!gInventory.isCategoryComplete(cat_id))
 		*/
 		{
-			gInventory.startBackgroundFetch(cat_id);
+			LLInventoryModelBackgroundFetch::instance().start(cat_id);
 		}
 
 		// Apply filter substring because it might have been changed
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index d40141c91d3a6de090085d7a66fa419a62667eca..dbc40959d703e9e1d3d34fbd29d0ededfadaa2b3 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -40,6 +40,7 @@
 #include "llfloaterinventory.h"
 #include "llinventorybridge.h"
 #include "llinventoryfunctions.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llinventorypanel.h"
 #include "llfiltereditor.h"
 #include "llfloaterreg.h"
@@ -419,7 +420,7 @@ void LLPanelMainInventory::onFilterEdit(const std::string& search_string )
 		return;
 	}
 
-	gInventory.startBackgroundFetch();
+	LLInventoryModelBackgroundFetch::instance().start();
 
 	mFilterSubString = search_string;
 	if (mActivePanel->getFilterSubString().empty() && mFilterSubString.empty())
@@ -499,7 +500,7 @@ void LLPanelMainInventory::onFilterSelected()
 	if (filter->isActive())
 	{
 		// If our filter is active we may be the first thing requiring a fetch so we better start it here.
-		gInventory.startBackgroundFetch();
+		LLInventoryModelBackgroundFetch::instance().start();
 	}
 	setFilterTextFromFilter();
 }
@@ -566,11 +567,11 @@ void LLPanelMainInventory::updateItemcountText()
 
 	std::string text = "";
 
-	if (LLInventoryModel::backgroundFetchActive())
+	if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive())
 	{
 		text = getString("ItemcountFetching", string_args);
 	}
-	else if (LLInventoryModel::isEverythingFetched())
+	else if (LLInventoryModelBackgroundFetch::instance().isEverythingFetched())
 	{
 		text = getString("ItemcountCompleted", string_args);
 	}
@@ -600,7 +601,7 @@ void LLPanelMainInventory::toggleFindOptions()
 		if (parent_floater) // Seraph: Fix this, shouldn't be null even for sidepanel
 			parent_floater->addDependentFloater(mFinderHandle);
 		// start background fetch of folders
-		gInventory.startBackgroundFetch();
+		LLInventoryModelBackgroundFetch::instance().start();
 	}
 	else
 	{
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index 6bda7d15467b4eb2b90296b407af568a9a663071..dd320f8328a64283ac81cc2f032c85b3f7a714fc 100644
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -43,6 +43,7 @@
 #include "llfloaterinventory.h"
 #include "llfoldervieweventlistener.h"
 #include "llinventoryfunctions.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llinventorypanel.h"
 #include "lllandmark.h"
 #include "lllineeditor.h"
@@ -217,7 +218,7 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)
 		getRootFolder()->scrollToShowSelection();
 	}
 
-	gInventory.startBackgroundFetch();
+	LLInventoryModelBackgroundFetch::instance().start();
 
 	if (mActivePanel->getFilterSubString().empty() && string.empty())
 	{
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index aa7b7b8636a0dc1ec81be09813e50c9d02936044..77b72dc728eb44f959359557e4ed1da367dd68c4 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -42,6 +42,7 @@
 #include "llstring.h"
 #include "lldir.h"
 #include "llfloaterreg.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llmultigesture.h"
 #include "llnotificationsutil.h"
 #include "llvfile.h"
@@ -131,10 +132,10 @@ LLPreviewGesture* LLPreviewGesture::show(const LLUUID& item_id, const LLUUID& ob
 	
 	// Start speculative download of sounds and animations
 	const LLUUID animation_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ANIMATION);
-	gInventory.startBackgroundFetch(animation_folder_id);
+	LLInventoryModelBackgroundFetch::instance().start(animation_folder_id);
 
 	const LLUUID sound_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SOUND);
-	gInventory.startBackgroundFetch(sound_folder_id);
+	LLInventoryModelBackgroundFetch::instance().start(sound_folder_id);
 
 	// this will call refresh when we have everything.
 	LLViewerInventoryItem* item = (LLViewerInventoryItem*)preview->getItem();
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index d75a1424d2cde4ad71928a7900dea7aadd53ff43..1a1dffe85c4d042c753ff763302231bec68aa7f7 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -62,6 +62,7 @@
 #include "llimfloater.h"
 #include "lllocationhistory.h"
 #include "llimageworker.h"
+
 #include "llloginflags.h"
 #include "llmd5.h"
 #include "llmemorystream.h"
@@ -116,6 +117,7 @@
 #include "llimagebmp.h"
 #include "llinventorybridge.h"
 #include "llinventorymodel.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llfriendcard.h"
 #include "llkeyboard.h"
 #include "llloginhandler.h"			// gLoginHandler, SLURL support
@@ -1846,7 +1848,7 @@ bool idle_startup()
 		}
 
         //DEV-17797.  get null folder.  Any items found here moved to Lost and Found
-        LLInventoryModel::findLostItems();
+        LLInventoryModelBackgroundFetch::instance().findLostItems();
 
 		LLStartUp::setStartupState( STATE_PRECACHE );
 		timeout.reset();
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 2b846d33fcdf408b322616c101363246506ab363..a1b3c8dabd5e52c50a1093e87564206e08c5d611 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -48,6 +48,7 @@
 #include "llfoldervieweventlistener.h"
 #include "llinventory.h"
 #include "llinventoryfunctions.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llinventoryobserver.h"
 #include "llinventorypanel.h"
 #include "llfloaterinventory.h"
@@ -1053,7 +1054,7 @@ class LLTextureFetchDescendentsObserver : public LLInventoryFetchDescendentsObse
 	{
 		// We need to find textures in all folders, so get the main
 		// background download going.
-		gInventory.startBackgroundFetch();
+		LLInventoryModelBackgroundFetch::instance().start();
 		gInventory.removeObserver(this);
 		delete this;
 	}
@@ -1074,9 +1075,9 @@ BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
 	{
 		showPicker(FALSE);
 		//grab textures first...
-		gInventory.startBackgroundFetch(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE));
+		LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE));
 		//...then start full inventory fetch.
-		gInventory.startBackgroundFetch();
+		LLInventoryModelBackgroundFetch::instance().start();
 		handled = TRUE;
 	}
 
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 75ec02f8eacc8c81cee3409db99ea16bd5546844..58d02be99a52b2b39987a9c857d80b767f48e904 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -45,6 +45,7 @@
 #include "llviewercontrol.h"
 #include "llconsole.h"
 #include "llinventorymodel.h"
+#include "llinventorymodelbackgroundfetch.h"
 #include "llgesturemgr.h"
 #include "llsidetray.h"
 
@@ -538,7 +539,7 @@ bool LLViewerInventoryCategory::fetchDescendents()
 		std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");
 		if (!url.empty()) //Capability found.  Build up LLSD and use it.
 		{
-			gInventory.startBackgroundFetch(mUUID);			
+			LLInventoryModelBackgroundFetch::instance().start(mUUID);			
 		}
 		else
 		{	//Deprecated, but if we don't have a capability, use the old system.