Updated llinventory to something closer to V2's implementation. Mostly just restructuring.

Most the changes are due to InventoryObjectList* changing to LLInventoryObject::object_list_t*, LLInventoryItem::II_FLAGS* changing to LLInventoryItemFlags::II_FLAGS* and also const'ing.
Certain perms for certain asset types(callcard&landmarks) have been laxed, as per LL's V2.
LLInventoryType now does lookups mostly though new lldictionary class.
LLLandmark using boost for callbacks, instead of custom class structure.
This commit is contained in:
Shyotl
2011-04-28 01:43:44 -05:00
parent 722a1dda04
commit 332cfdb532
52 changed files with 1178 additions and 786 deletions

View File

@@ -72,18 +72,6 @@ public:
virtual void changed(U32 mask) = 0;
std::string mMessageName; // used by Agent Inventory Service only. [DEV-20328]
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInventoryModel
//
// This class represents a collection of inventory, and provides
// efficient ways to access that information. This class could in
// theory be used for any place where you need inventory, though it
// optimizes for time efficiency - not space efficiency, probably
// making it inappropriate for use on tasks.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLInventoryObject;
class LLInventoryItem;
class LLInventoryCategory;
@@ -94,159 +82,255 @@ class LLViewerInventoryCategory;
class LLMessageSystem;
class LLInventoryCollectFunctor;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLInventoryModel
//
// Represents a collection of inventory, and provides efficient ways to access
// that information.
// NOTE: This class could in theory be used for any place where you need
// inventory, though it optimizes for time efficiency - not space efficiency,
// probably making it inappropriate for use on tasks.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLInventoryModel
{
public:
typedef enum e_has_children
enum EHasChildren
{
CHILDREN_NO,
CHILDREN_YES,
CHILDREN_MAYBE
}EHasChildren;
};
// These are used a lot...
typedef LLDynamicArray<LLPointer<LLViewerInventoryCategory> > cat_array_t;
typedef LLDynamicArray<LLPointer<LLViewerInventoryItem> > item_array_t;
// construction & destruction
LLInventoryModel();
~LLInventoryModel();
typedef std::set<LLUUID> changed_items_t;
class fetchInventoryResponder: public LLHTTPClient::Responder
class fetchInventoryResponder : public LLHTTPClient::Responder
{
public:
fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
void result(const LLSD& content);
void error(U32 status, const std::string& reason);
public:
typedef std::vector<LLViewerInventoryCategory*> folder_ref_t;
protected:
LLSD mRequestSD;
};
//
// Accessors
//
/********************************************************************************
** **
** INITIALIZATION/SETUP
**/
// This is a convenience function to check if one object has a
// parent chain up to the category specified by UUID.
BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id, const BOOL break_on_recursion=FALSE);
//--------------------------------------------------------------------
// Constructors / Destructors
//--------------------------------------------------------------------
public:
LLInventoryModel();
~LLInventoryModel();
//<edit>
//protected:
//</edit>
void empty(); // empty the entire contents
// Get the object by id. Returns NULL if not found.
// * WARNING: use the pointer returned for read operations - do
// not modify the object values in place or you will break stuff.
LLInventoryObject* getObject(const LLUUID& id) const;
//--------------------------------------------------------------------
// Initialization
//--------------------------------------------------------------------
public:
// The inventory model usage is sensitive to the initial construction of the model
bool isInventoryUsable() const;
private:
bool mIsAgentInvUsable; // used to handle an invalid inventory state
// Get the item by id. Returns NULL if not found.
// * WARNING: use the pointer for read operations - use the
// updateItem() method to actually modify values.
LLViewerInventoryItem* getItem(const LLUUID& id) const;
//--------------------------------------------------------------------
// Structure
//--------------------------------------------------------------------
public:
// Methods to load up inventory skeleton & meat. These are used
// during authentication. Returns true if everything parsed.
bool loadSkeleton(const LLSD& options, const LLUUID& owner_id);
void buildParentChildMap(); // brute force method to rebuild the entire parent-child relations
// Call on logout to save a terse representation.
void cache(const LLUUID& parent_folder_id, const LLUUID& agent_id);
private:
// Information for tracking the actual inventory. We index this
// information in a lot of different ways so we can access
// the inventory using several different identifiers.
// mInventory member data is the 'master' list of inventory, and
// mCategoryMap and mItemMap store uuid->object mappings.
typedef std::map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t;
typedef std::map<LLUUID, LLPointer<LLViewerInventoryItem> > item_map_t;
cat_map_t mCategoryMap;
item_map_t mItemMap;
// This last set of indices is used to map parents to children.
typedef std::map<LLUUID, cat_array_t*> parent_cat_map_t;
typedef std::map<LLUUID, item_array_t*> parent_item_map_t;
parent_cat_map_t mParentChildCategoryTree;
parent_item_map_t mParentChildItemTree;
// Get the category by id. Returns NULL if not found.
// * WARNING: use the pointer for read operations - use the
// updateCategory() method to actually modify values.
LLViewerInventoryCategory* getCategory(const LLUUID& id) const;
//--------------------------------------------------------------------
// Login
//--------------------------------------------------------------------
const static S32 sCurrentInvCacheVersion; // expected inventory cache version
// Return the number of items or categories
S32 getItemCount() const;
S32 getCategoryCount() const;
/** Initialization/Setup
** **
*******************************************************************************/
/********************************************************************************
** **
** ACCESSORS
**/
//--------------------------------------------------------------------
// Descendents
//--------------------------------------------------------------------
public:
// Make sure we have the descendents in the structure. Returns true
// if a fetch was performed.
bool fetchDescendentsOf(const LLUUID& folder_id) const;
// Return the direct descendents of the id provided.Set passed
// in values to NULL if the call fails.
// *WARNING: The array provided points straight into the guts of
// this object, and should only be used for read operations, since
// modifications may invalidate the internal state of the
// inventory.
// NOTE: The array provided points straight into the guts of
// this object, and should only be used for read operations, since
// modifications may invalidate the internal state of the inventory.
void getDirectDescendentsOf(const LLUUID& cat_id,
cat_array_t*& categories,
item_array_t*& items) const;
// SJB: Added version to lock the arrays to catch potential logic bugs
void lockDirectDescendentArrays(const LLUUID& cat_id,
cat_array_t*& categories,
item_array_t*& items);
void unlockDirectDescendentArrays(const LLUUID& cat_id);
// Starting with the object specified, add it's descendents to the
// Starting with the object specified, add its descendents to the
// array provided, but do not add the inventory object specified
// by id. There is no guaranteed order. Neither array will be
// erased before adding objects to it. Do not store a copy of the
// pointers collected - use them, and collect them again later if
// you need to reference the same objects.
enum { EXCLUDE_TRASH = FALSE, INCLUDE_TRASH = TRUE };
// by id. There is no guaranteed order.
// NOTE: Neither array will be erased before adding objects to it.
// Do not store a copy of the pointers collected - use them, and
// collect them again later if you need to reference the same objects.
enum {
EXCLUDE_TRASH = FALSE,
INCLUDE_TRASH = TRUE
};
void collectDescendents(const LLUUID& id,
cat_array_t& categories,
item_array_t& items,
BOOL include_trash);
void collectDescendentsIf(const LLUUID& id,
cat_array_t& categories,
item_array_t& items,
BOOL include_trash,
LLInventoryCollectFunctor& add,
BOOL follow_folder_links = FALSE);
// Collect all items in inventory that are linked to item_id.
// Assumes item_id is itself not a linked item.
item_array_t collectLinkedItems(const LLUUID& item_id,
const LLUUID& start_folder_id = LLUUID::null);
// Get the inventoryID that this item points to, else just return item_id
// Check if one object has a parent chain up to the category specified by UUID.
BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id, const BOOL break_on_recursion=FALSE) const;
//--------------------------------------------------------------------
// Find
//--------------------------------------------------------------------
public:
// Returns the uuid of the category that specifies 'type' as what it
// defaults to containing. The category is not necessarily only for that type.
// NOTE: If create_folder is true, this will create a new inventory category
// on the fly if one does not exist. *NOTE: if find_in_library is true it
// will search in the user's library folder instead of "My Inventory"
const LLUUID findCategoryUUIDForType(LLAssetType::EType preferred_type,
bool create_folder = true
/*,bool find_in_library = false*/);
// Get whatever special folder this object is a child of, if any.
const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const;
// Get the object by id. Returns NULL if not found.
// NOTE: Use the pointer returned for read operations - do
// not modify the object values in place or you will break stuff.
LLInventoryObject* getObject(const LLUUID& id) const;
// Get the item by id. Returns NULL if not found.
// NOTE: Use the pointer for read operations - use the
// updateItem() method to actually modify values.
LLViewerInventoryItem* getItem(const LLUUID& id) const;
// Get the category by id. Returns NULL if not found.
// NOTE: Use the pointer for read operations - use the
// updateCategory() method to actually modify values.
LLViewerInventoryCategory* getCategory(const LLUUID& id) const;
// Get the inventoryID or item that this item points to, else just return object_id
const LLUUID& getLinkedItemID(const LLUUID& object_id) const;
LLViewerInventoryItem* getLinkedItem(const LLUUID& object_id) const;
LLUUID findCategoryByName(std::string name);
private:
mutable LLPointer<LLViewerInventoryItem> mLastItem; // cache recent lookups
// This method will return false if this inventory model is in an usabel state.
// The inventory model usage is sensitive to the initial construction of the
// model.
bool isInventoryUsable();
//--------------------------------------------------------------------
// Count
//--------------------------------------------------------------------
public:
// Return the number of items or categories
S32 getItemCount() const;
S32 getCategoryCount() const;
//
// Mutators
//
/** Accessors
** **
*******************************************************************************/
// Calling this method with an inventory item will either change
// an existing item with a matching item_id, or will add the item
/********************************************************************************
** **
** MUTATORS
**/
public:
// Change an existing item with a matching item_id or add the item
// to the current inventory. Returns the change mask generated by
// the update. No notifcation will be sent to observers. This
// the update. No notification will be sent to observers. This
// method will only generate network traffic if the item had to be
// reparented.
// *NOTE: In usage, you will want to perform cache accounting
// operations in LLInventoryModel::accountForUpdate() or
// LLViewerInventoryItem::updateServer() before calling this
// method.
// NOTE: In usage, you will want to perform cache accounting
// operations in LLInventoryModel::accountForUpdate() or
// LLViewerInventoryItem::updateServer() before calling this method.
U32 updateItem(const LLViewerInventoryItem* item);
// Calling this method with an inventory category will either
// change an existing item with the matching id, or it will add
// Change an existing item with the matching id or add
// the category. No notifcation will be sent to observers. This
// method will only generate network traffic if the item had to be
// reparented.
// *NOTE: In usage, you will want to perform cache accounting
// operations in LLInventoryModel::accountForUpdate() or
// LLViewerInventoryCategory::updateServer() before calling this
// method.
// NOTE: In usage, you will want to perform cache accounting
// operations in accountForUpdate() or LLViewerInventoryCategory::
// updateServer() before calling this method.
void updateCategory(const LLViewerInventoryCategory* cat);
// This method will move the specified object id to the specified
// category, update the internal structures. No cache accounting,
// Move the specified object id to the specified category and
// update the internal structures. No cache accounting,
// observer notification, or server update is performed.
void moveObject(const LLUUID& object_id, const LLUUID& cat_id);
// delete a particular inventory object by ID. This will purge one
// object from the internal data structures maintaining a
// cosistent internal state. No cache accounting, observer
//--------------------------------------------------------------------
// Delete
//--------------------------------------------------------------------
public:
// Delete a particular inventory object by ID. Will purge one
// object from the internal data structures, maintaining a
// consistent internal state. No cache accounting, observer
// notification, or server update is performed.
void deleteObject(const LLUUID& id);
// Delete a particular inventory object by ID, and delete it from
// the server. Also updates linked items.
void purgeObject(const LLUUID& id);
// This is a method which collects the descendents of the id
// Collects and purges the descendants of the id
// provided. If the category is not found, no action is
// taken. This method goes through the long winded process of
// removing server representation of folders and items while doing
// cache accounting in a fairly efficient manner. This method does
// not notify observers (though maybe it shouldd...)
// not notify observers (though maybe it should...)
void purgeDescendentsOf(const LLUUID& id);
// This method optimally removes the referenced categories and
@@ -256,51 +340,15 @@ public:
void deleteFromServer(LLDynamicArray<LLUUID>& category_ids,
LLDynamicArray<LLUUID>& item_ids);
// Add/remove an observer. If the observer is destroyed, be sure
// to remove it.
void addObserver(LLInventoryObserver* observer);
void removeObserver(LLInventoryObserver* observer);
BOOL containsObserver(LLInventoryObserver* observer);
//
// Misc Methods
//
// findCategoryUUIDForType() returns the uuid of the category that
// specifies 'type' as what it defaults to containing. The
// category is not necessarily only for that type. *NOTE: This
// will create a new inventory category on the fly if one does not
// exist.
// SDK: Added flag to specify whether the folder should be created if not found. This fixes the horrible
// multiple trash can bug.
LLUUID findCategoryUUIDForType(LLAssetType::EType preferred_type, bool create_folder = true);
// Get whatever special folder this object is a child of, if any.
const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const;
// Call this method when it's time to update everyone on a new
// state, by default, the inventory model will not update
// observers automatically.
// The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328]
void notifyObservers(const std::string service_name="");
// This allows outsiders to tell the inventory if something has
// been changed 'under the hood', but outside the control of the
// inventory. For example, if we grant someone modify permissions,
// then that changes the data structures for LLAvatarTracker, but
// potentially affects inventory observers. This API makes sure
// that the next notify will include that notification.
void addChangedMask(U32 mask, const LLUUID& referent);
const std::set<LLUUID>& getChangedIDs() { return mChangedItemIDs; }
// This method to prepares a set of mock inventory which provides
// minimal functionality before the actual arrival of inventory.
//void mock(const LLUUID& root_id);
// make sure we have the descendents in the structure.
void fetchDescendentsOf(const LLUUID& folder_id);
// Add categories to a list to be fetched in bulk.
static void bulkFetch(std::string url);
@@ -308,27 +356,27 @@ public:
// call this method to request the inventory.
//void requestFromServer(const LLUUID& agent_id);
// call this method on logout to save a terse representation
void cache(const LLUUID& parent_folder_id, const LLUUID& agent_id);
// Generates a string containing the path to the item specified by
// item_id.
void appendPath(const LLUUID& id, std::string& path);
// message handling functionality
static void registerCallbacks(LLMessageSystem* msg);
// Convenience function to create a new category. You could call
// updateCatgory() with a newly generated UUID category, but this
// version will take care of details like what the name should be
// based on preferred type. Returns the UUID of the new
// category. If you want to use the default name based on type,
// pass in a NULL to the 'name parameter.
//--------------------------------------------------------------------
// Creation
//--------------------------------------------------------------------
public:
// Returns the UUID of the new category. If you want to use the default
// name based on type, pass in a NULL to the 'name' parameter.
LLUUID createNewCategory(const LLUUID& parent_id,
LLAssetType::EType preferred_type,
const std::string& name);
LLUUID findCategoryByName(std::string name);
// Internal methods that add inventory and make sure that all of
// the internal data structures are consistent. These methods
// should be passed pointers of newly created objects, and the
// instance will take over the memory management from there.
void addCategory(LLViewerInventoryCategory* category);
void addItem(LLViewerInventoryItem* item);
// methods to load up inventory skeleton & meat. These are used
// during authentication. return true if everything parsed.
@@ -339,19 +387,19 @@ public:
//... we do inventory queries on should be examined, and the usage of
//... the skeleton in querying the wearables needs to be examined as well.
bool loadSkeleton(const options_t& options, const LLUUID& owner_id);
bool loadSkeleton(const LLSD& options, const LLUUID& owner_id);
bool loadMeat(const options_t& options, const LLUUID& owner_id);
// This is a brute force method to rebuild the entire parent-child
// relations.
void buildParentChildMap();
/** Mutators
** **
*******************************************************************************/
//
// Category accounting.
//
/********************************************************************************
** **
** CATEGORY ACCOUNTING
**/
// This structure represents the number of items added or removed
// from a category.
public:
// Represents the number of items added or removed from a category.
struct LLCategoryUpdate
{
LLCategoryUpdate() : mDescendentDelta(0) {}
@@ -363,8 +411,7 @@ public:
};
typedef std::vector<LLCategoryUpdate> update_list_t;
// This structure eixts to make it easier to account for deltas in
// a map.
// This exists to make it easier to account for deltas in a map.
struct LLInitializedS32
{
LLInitializedS32() : mValue(0) {}
@@ -375,21 +422,59 @@ public:
};
typedef std::map<LLUUID, LLInitializedS32> update_map_t;
// Call these methods when there are category updates, but call
// them *before* the actual update so the method can do descendent
// accounting correctly.
void accountForUpdate(const LLCategoryUpdate& update);
// Call when there are category updates. Call them *before* the
// actual update so the method can do descendent accounting correctly.
void accountForUpdate(const LLCategoryUpdate& update) const;
void accountForUpdate(const update_list_t& updates);
void accountForUpdate(const update_map_t& updates);
// Return child status of category children. yes/no/maybe
// Return (yes/no/maybe) child status of category children.
EHasChildren categoryHasChildren(const LLUUID& cat_id) const;
// returns true iff category version is known and theoretical
// Returns true iff category version is known and theoretical
// descendents == actual descendents.
bool isCategoryComplete(const LLUUID& cat_id) const;
/** Category Accounting
** **
*******************************************************************************/
// start and stop background breadth-first fetching of inventory contents
/********************************************************************************
** **
** NOTIFICATIONS
**/
public:
// Call to explicitly update everyone on a new state. The optional argument
// 'service_name' is used by Agent Inventory Service [DEV-20328]
void notifyObservers(const std::string service_name="");
// Allows outsiders to tell the inventory if something has
// been changed 'under the hood', but outside the control of the
// inventory. The next notify will include that notification.
void addChangedMask(U32 mask, const LLUUID& referent);
const changed_items_t& getChangedIDs() const { return mChangedItemIDs; }
protected:
// Updates all linked items pointing to this id.
void addChangedMaskForLinks(const LLUUID& object_id, U32 mask);
private:
// Variables used to track what has changed since the last notify.
U32 mModifyMask;
changed_items_t mChangedItemIDs;
//--------------------------------------------------------------------
// Observers
//--------------------------------------------------------------------
public:
// If the observer is destroyed, be sure to remove it.
void addObserver(LLInventoryObserver* observer);
void removeObserver(LLInventoryObserver* observer);
BOOL containsObserver(LLInventoryObserver* observer) const;
private:
typedef std::set<LLInventoryObserver*> observer_list_t;
observer_list_t mObservers;
public:
// this gets triggered when performing a filter-search
static void startBackgroundFetch(const LLUUID& cat_id = LLUUID::null); // start fetch process
static void findLostItems();
@@ -404,20 +489,12 @@ protected:
// should be passed pointers of newly created objects, and the
// instance will take over the memory management from there.
// <edit>
public:
// </edit>
void addCategory(LLViewerInventoryCategory* category);
void addItem(LLViewerInventoryItem* item);
// <edit>
//protected:
// </edit>
// Internal method which looks for a category with the specified
// preferred type. Returns LLUUID::null if not found
LLUUID findCatUUID(LLAssetType::EType preferred_type);
// Empty the entire contents
void empty();
// Given the current state of the inventory items, figure out the
// clone information. *FIX: This is sub-optimal, since we can
@@ -427,8 +504,27 @@ public:
// file import/export.
// <edit>
/** Notifications
** **
*******************************************************************************/
/********************************************************************************
** **
** MISCELLANEOUS
**/
//--------------------------------------------------------------------
// Callbacks
//--------------------------------------------------------------------
public:
// </edit>
static void registerCallbacks(LLMessageSystem* msg);
//--------------------------------------------------------------------
// File I/O
//--------------------------------------------------------------------
protected:
friend class LLLocalInventory;
static bool loadFromFile(const std::string& filename,
cat_array_t& categories,
item_array_t& items,
@@ -436,65 +532,37 @@ public:
static bool saveToFile(const std::string& filename,
const cat_array_t& categories,
const item_array_t& items);
// <edit>
protected:
// </edit>
// message handling functionality
//static void processUseCachedInventory(LLMessageSystem* msg, void**);
//--------------------------------------------------------------------
// Message handling functionality
//--------------------------------------------------------------------
public:
static void processUpdateCreateInventoryItem(LLMessageSystem* msg, void**);
static void processRemoveInventoryItem(LLMessageSystem* msg, void**);
static void processUpdateInventoryFolder(LLMessageSystem* msg, void**);
static void processRemoveInventoryFolder(LLMessageSystem* msg, void**);
//static void processExchangeCallingcard(LLMessageSystem* msg, void**);
//static void processAddCallingcard(LLMessageSystem* msg, void**);
//static void processDeclineCallingcard(LLMessageSystem* msg, void**);
static void processSaveAssetIntoInventory(LLMessageSystem* msg, void**);
static void processBulkUpdateInventory(LLMessageSystem* msg, void**);
static void processInventoryDescendents(LLMessageSystem* msg, void**);
static void processMoveInventoryItem(LLMessageSystem* msg, void**);
static void processFetchInventoryReply(LLMessageSystem* msg, void**);
protected:
bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting);
// Updates all linked items pointing to this id.
void addChangedMaskForLinks(const LLUUID& object_id, U32 mask);
//--------------------------------------------------------------------
// Locks
//--------------------------------------------------------------------
public:
void lockDirectDescendentArrays(const LLUUID& cat_id,
cat_array_t*& categories,
item_array_t*& items);
void unlockDirectDescendentArrays(const LLUUID& cat_id);
protected:
cat_array_t* getUnlockedCatArray(const LLUUID& id);
item_array_t* getUnlockedItemArray(const LLUUID& id);
protected:
// Varaibles used to track what has changed since the last notify.
U32 mModifyMask;
typedef std::set<LLUUID> changed_items_t;
changed_items_t mChangedItemIDs;
// Information for tracking the actual inventory. We index this
// information in a lot of different ways so we can access
// the inventory using several different identifiers.
// mInventory member data is the 'master' list of inventory, and
// mCategoryMap and mItemMap store uuid->object mappings.
typedef std::map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t;
typedef std::map<LLUUID, LLPointer<LLViewerInventoryItem> > item_map_t;
//inv_map_t mInventory;
cat_map_t mCategoryMap;
item_map_t mItemMap;
private:
std::map<LLUUID, bool> mCategoryLock;
std::map<LLUUID, bool> mItemLock;
// cache recent lookups
mutable LLPointer<LLViewerInventoryItem> mLastItem;
// This last set of indices is used to map parents to children.
typedef std::map<LLUUID, cat_array_t*> parent_cat_map_t;
typedef std::map<LLUUID, item_array_t*> parent_item_map_t;
parent_cat_map_t mParentChildCategoryTree;
parent_item_map_t mParentChildItemTree;
typedef std::set<LLInventoryObserver*> observer_list_t;
observer_list_t mObservers;
// completing the fetch once per session should be sufficient
static BOOL sBackgroundFetchActive;
@@ -505,20 +573,19 @@ protected:
static F32 sMaxTimeBetweenFetches;
static S16 sBulkFetchCount;
// This flag is used to handle an invalid inventory state.
bool mIsAgentInvUsable;
private:
const static S32 sCurrentInvCacheVersion; // expected inventory cache version
public:
// *NOTE: DEBUG functionality
void dumpInventory();
void dumpInventory() const;
static bool isBulkFetchProcessingComplete();
static void stopBackgroundFetch(); // stop fetch process
static BOOL sFullFetchStarted;
static BOOL sAllFoldersFetched;
/** Miscellaneous
** **
*******************************************************************************/
};
// a special inventory model for the agent