/// <summary> /// Load xml. /// </summary> /// <param name="_stream">irrlife stream.</param> /// <param name="_stream">animation's xml stream.</param> private void Run(Stream stream, Stream animStream) { using (XmlTextReader reader = new XmlTextReader(stream)) { XmlTextReader animReader = null; if (animStream != null) animReader = new XmlTextReader(animStream); while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { // root if (reader.Name == "attributes") { } // node data. else if (reader.Name == "node") { if (datas == null) datas = new List<IrrDatas>(); IrrDatas data = new IrrDatas(reader, true); if (animReader != null) data.CreateAnimationKey(animReader); datas.Add(data); } } } if (animReader != null) animReader.Close(); reader.Close(); } }
public void AddNewObject(UUID _uuid, IrrDatas _data) { lock (dataList) { if (dataList.ContainsKey(_uuid)) { // we have a duplicate key - do nothing. what this means is that // we fetched this asset twice, because e.g. two prims had the same // mesh, each prim checked the dataList and saw that the mesh wasn't downloaded, // and each prim started a download, then one prim finished its download and // inserted it into the list, then later the 2nd prim finished and tried to // insert but it was too late. // // solutions that we can't use: // // - we shouldn't lock the entire list during fetching an asset because that // would block fetching of other incoming asset requests that may be coming from // other mesh prims that are loading in from libomv. // // - we shouldn't do an atomic check-and-insert into dataList because the // current meaning of an entry in dataList is "this (.irr) asset and all // its related data has been *completely downloaded* and is *ready to use*". // if we did an atomic check-and-insert we would be inserting into this list // before the data is actually downloaded and ready to use. // // this means that the solution is to maintain two separate lists: // 1. inProgressIrrfileRequests // 2. completelyDownloadedIrrfiles // // 1 is atomically check-and-updated at the time the mesh prim arrives. // this prevents duplicate requests. 2 is updated after the download is // complete, and the corresponding entry in 1 is removed. // // during the check-and-update of 1, if we find that the request already // exists (from a different prim), but the asset isn't yet downloaded // completely, we have to wait (e.g. for an event, or later poll a queue). // // currently the solution of 2 separate lists is not yet implemented. // the above workaround should prevent errors but may cause wasted bandwidth // in the case of multiple mesh prims arriving at the same time that use // the same mesh and all issue the same download request. // } else { dataList.Add(_uuid, _data); } } }