Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
Help about MediaWiki
Special pages
Open Simulator Technical Help
Search
Search
Appearance
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
OpenSimulator Internals/Connector Architecture/Inventory Connector
(section)
Page
Discussion
English
Read
Edit
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
View history
General
What links here
Related changes
Page information
Appearance
move to sidebar
hide
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
= OpenSimulator Internals/Connector Architecture/Inventory Connector = == Overview == XInventoryServicesConnector is the simulator-side remote connector for IInventoryService. It translates IInventoryService calls into HTTP POST requests to the ROBUST XInventory handler at /xinventory. Source file: OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs ---- === Initialisation === Config section: [InventoryService] (or configName argument if provided) Required key: * InventoryServerURI -- URL of the ROBUST inventory endpoint; throws if missing The endpoint URL is always InventoryServerURI + "/xinventory" (trailing slash normalized). Optional key: * RemoteRequestTimeout -- timeout in seconds for HTTP requests; default -1 (100 seconds, not infinite) A stats counter (RequestsMade) is registered with StatsManager on initialisation. Four constructors: * Default (no args) -- URI must be set externally * String URI -- used by callers that pass the URI directly; appends /xinventory * IConfigSource -- calls Initialise(), normal grid mode * IConfigSource + configName -- used for non-default section names ---- === Transport === Unlike other connectors, XInventoryServicesConnector does not use SynchronousRestFormsRequester. It has its own MakePostDicRequest() method using HttpClient directly. MakePostDicRequest() features: * Uses WebUtil.GetNewGlobalHttpClient() with configured timeout * Sends Keep-Alive headers (timeout=30, max=10) * Sends Content-Type: application/x-www-form-urlencoded * Uses HttpCompletionOption.ResponseHeadersRead -- reads headers first, then streams body * Body receive has its own CancellationTokenSource timeout via WebUtil.EstimatedReceiveTimeout() * Logs requests taking longer than WebUtil.LongCallTime * Logs body timeouts separately from other errors * Always disposes request, response, and client in finally block * Returns empty Dictionary on null response (never returns null) All requests are POST to m_InventoryURL. The METHOD and parameters are encoded as URL query string in the POST body. MakeRequest() increments RequestsMade counter on every call. ---- === Item Cache === Static ExpiringCacheOS<UUID, InventoryItemBase> shared across all instances. TTL is 30 seconds. Cache is checked in GetItem() and GetMultipleItems() before making remote requests. Cache is updated on successful GetItem(), UpdateItem(), and GetMultipleItems(). Cache entries are removed on MoveItems() and DeleteItems(). ---- === CheckReturn() === Helper used by most methods. Returns false if the reply dictionary is null or empty. If RESULT key exists and its value parses as bool, returns that bool. If RESULT key exists but is not parseable as bool, returns false. If RESULT key is absent, returns true (assumes success if the server returned any data). GetAssetPermissions() cannot use CheckReturn() because its RESULT is an int, not a bool -- it has its own inline parse. ---- === Methods === {| class="wikitable" ! Method !! METHOD field !! Notes |- | CreateUserInventory(principalID) || CREATEUSERINVENTORY || Returns bool |- | GetInventorySkeleton(principalID) || GETINVENTORYSKELETON || Returns List<InventoryFolderBase> from FOLDERS dict |- | GetRootFolder(principalID) || GETROOTFOLDER || Returns single InventoryFolderBase from "folder" key |- | GetFolderForType(principalID, type) || GETFOLDERFORTYPE || TYPE sent as int |- | GetFolderContent(principalID, folderID) || GETFOLDERCONTENT || Returns InventoryCollection with Folders and Items lists |- | GetMultipleFoldersContent(principalID, folderIDs[]) || GETMULTIPLEFOLDERSCONTENT || Batch; results keyed as F_{uuid}; null entry per missing folder |- | GetFolderItems(principalID, folderID) || GETFOLDERITEMS || Returns List<InventoryItemBase> from ITEMS dict |- | AddFolder(folder) || ADDFOLDER || Sends full folder fields as dictionary |- | UpdateFolder(folder) || UPDATEFOLDER || Sends fields as query string; URL-encodes Name |- | MoveFolder(folder) || MOVEFOLDER || Sends ParentID, ID, PRINCIPAL only |- | DeleteFolders(principalID, folderIDs) || DELETEFOLDERS || Sends FOLDERS as List<string> |- | PurgeFolder(folder) || PURGEFOLDER || Sends ID only |- | AddItem(item) || ADDITEM || Sends full item fields; null-coalesces Description, CreatorData, CreatorId |- | UpdateItem(item) || UPDATEITEM || Updates cache on success |- | MoveItems(principalID, items) || MOVEITEMS || Sends parallel IDLIST and DESTLIST; removes from cache |- | DeleteItems(principalID, itemIDs) || DELETEITEMS || Removes from cache |- | GetItem(principalID, itemID) || GETITEM || Cache-first; updates cache on fetch |- | GetMultipleItems(principalID, itemIDs[]) || GETMULTIPLEITEMS || Cache-first per item; only fetches uncached IDs; results keyed as item_N |- | GetFolder(principalID, folderID) || GETFOLDER || Returns single InventoryFolderBase |- | GetActiveGestures(principalID) || GETACTIVEGESTURES || Returns List<InventoryItemBase> from ITEMS dict |- | GetAssetPermissions(principalID, assetID) || GETASSETPERMISSIONS || Returns int from RESULT field; 0 on failure |- | HasInventoryForUser(principalID) || (none) || Always returns false -- not implemented for remote connector |} ---- === BuildFolder() / BuildItem() === Static helpers that construct InventoryFolderBase and InventoryItemBase from reply dictionaries. Both catch exceptions and return an empty object on parse failure rather than throwing. CreatorData is optional in BuildItem() -- fetched via TryGetValue. ---- === Notes === * This is the only connector in the set that uses HttpClient directly rather than SynchronousRestFormsRequester. * HasInventoryForUser() always returns false -- not implemented. * GetMultipleItems() builds the request body with a StringBuilder, skipping items already in cache. The result index tracking (variable i) carries over between the cache-hit loop and the network-result loop -- order of itemArr entries may not match order of itemIDs if some were cached and some were not. * GetMultipleFoldersContent() returns null entries (not omits) for folders not found in the reply, preserving index alignment with the input folderIDs array. * UpdateFolder() URL-encodes Name via HttpUtility.UrlEncode() but AddFolder() does not -- inconsistency within the same file. ---- == See Also == * [[OpenSimulator Internals/Connector Architecture]] * [[OpenSimulator Internals/Code Map/ROBUST/InventoryService]] * [[OpenSimulator Internals/Code Map/Shared]]
Summary:
Please note that all contributions to Open Simulator Technical Help may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
Open Simulator Technical Help:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Search
Search
Editing
OpenSimulator Internals/Connector Architecture/Inventory Connector
(section)
Add topic