Beispiel #1
0
        /// <summary>
        /// Loads in inventory cache file into the inventory structure. Note only valid to call after login has been successful.
        /// </summary>
        /// <param name="filename">Name of the cache file to load</param>
        /// <returns>The number of inventory items sucessfully reconstructed into the inventory node tree</returns>
        public int RestoreFromDisk(string filename)
        {
            List <InventoryNode> nodes = new List <InventoryNode>();
            int item_count             = 0;

            try
            {
                if (!File.Exists(filename))
                {
                    return(-1);
                }

                using (Stream stream = File.Open(filename, FileMode.Open))
                {
                    BinaryFormatter bformatter = new BinaryFormatter();

                    while (stream.Position < stream.Length)
                    {
                        OpenMetaverse.InventoryNode node = (InventoryNode)bformatter.Deserialize(stream);
                        nodes.Add(node);
                        item_count++;
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Log("Error accessing inventory cache file :" + e.Message, Helpers.LogLevel.Error);
                return(-1);
            }

            Logger.Log("Read " + item_count.ToString() + " items from inventory cache file", Helpers.LogLevel.Info);

            item_count = 0;
            List <InventoryNode> del_nodes     = new List <InventoryNode>(); //nodes that we have processed and will delete
            List <UUID>          dirty_folders = new List <UUID>();          // Tainted folders that we will not restore items into

            // Because we could get child nodes before parents we must itterate around and only add nodes who have
            // a parent already in the list because we must update both child and parent to link together
            // But sometimes we have seen orphin nodes due to bad/incomplete data when caching so we have an emergency abort route
            int stuck = 0;

            while (nodes.Count != 0 && stuck < 5)
            {
                foreach (InventoryNode node in nodes)
                {
                    InventoryNode pnode;
                    if (node.ParentID == UUID.Zero)
                    {
                        //We don't need the root nodes "My Inventory" etc as they will already exist for the correct
                        // user of this cache.
                        del_nodes.Add(node);
                        item_count--;
                    }
                    else if (Items.TryGetValue(node.Data.UUID, out pnode))
                    {
                        //We already have this it must be a folder
                        if (node.Data is InventoryFolder)
                        {
                            InventoryFolder cache_folder  = (InventoryFolder)node.Data;
                            InventoryFolder server_folder = (InventoryFolder)pnode.Data;

                            if (cache_folder.Version != server_folder.Version)
                            {
                                Logger.DebugLog("Inventory Cache/Server version mismatch on " + node.Data.Name + " " + cache_folder.Version.ToString() + " vs " + server_folder.Version.ToString());
                                pnode.NeedsUpdate = true;
                                dirty_folders.Add(node.Data.UUID);
                            }
                            else
                            {
                                pnode.NeedsUpdate = false;
                            }

                            del_nodes.Add(node);
                        }
                    }
                    else if (Items.TryGetValue(node.ParentID, out pnode))
                    {
                        if (node.Data != null)
                        {
                            // If node is folder, and it does not exist in skeleton, mark it as
                            // dirty and don't process nodes that belong to it
                            if (node.Data is InventoryFolder && !(Items.ContainsKey(node.Data.UUID)))
                            {
                                dirty_folders.Add(node.Data.UUID);
                            }

                            //Only add new items, this is most likely to be run at login time before any inventory
                            //nodes other than the root are populated. Don't add non existing folders.
                            if (!Items.ContainsKey(node.Data.UUID) && !dirty_folders.Contains(pnode.Data.UUID) && !(node.Data is InventoryFolder))
                            {
                                Items.Add(node.Data.UUID, node);
                                node.Parent = pnode;                   //Update this node with its parent
                                pnode.Nodes.Add(node.Data.UUID, node); // Add to the parents child list
                                item_count++;
                            }
                        }

                        del_nodes.Add(node);
                    }
                }

                if (del_nodes.Count == 0)
                {
                    stuck++;
                }
                else
                {
                    stuck = 0;
                }

                //Clean up processed nodes this loop around.
                foreach (InventoryNode node in del_nodes)
                {
                    nodes.Remove(node);
                }

                del_nodes.Clear();
            }

            Logger.Log("Reassembled " + item_count.ToString() + " items from inventory cache file", Helpers.LogLevel.Info);
            return(item_count);
        }
Beispiel #2
0
        /// <summary>
        /// Loads in inventory cache file into the inventory structure. Note only valid to call after login has been successful.
        /// </summary>
        /// <param name="filename">Name of the cache file to load</param>
        public void read_inventory_cache(string filename)
        {
            List <InventoryNode> nodes = new List <InventoryNode>();
            int item_count             = 0;

            try
            {
                if (!File.Exists(filename))
                {
                    return;
                }

                Stream          stream     = File.Open(filename, FileMode.Open);
                BinaryFormatter bformatter = new BinaryFormatter();

                while (stream.Position < stream.Length)
                {
                    OpenMetaverse.InventoryNode node = (InventoryNode)bformatter.Deserialize(stream);
                    nodes.Add(node);
                    item_count++;
                }

                stream.Close();
            }
            catch (Exception e)
            {
                Logger.Log("Error accessing inventory cache file :" + e.Message, Helpers.LogLevel.Error);
                return;
            }

            Logger.Log("Read " + item_count.ToString() + " items from inventory cache file", Helpers.LogLevel.Info);

            item_count = 0;

            List <InventoryNode> del_nodes = new List <InventoryNode>();

            // Becuase we could get child nodes before parents we must itterate around and only add nodes who have
            // a parent already in the list because we must update both child and parent to link together
            while (nodes.Count != 0)
            {
                foreach (InventoryNode node in nodes)
                {
                    InventoryNode pnode;
                    if (node.ParentID == UUID.Zero)
                    {
                        //We don't need the root nodes "My Inventory" etc as they will already exist for the correct
                        // user of this cache.
                        del_nodes.Add(node);
                    }
                    else if (Items.TryGetValue(node.ParentID, out pnode))
                    {
                        if (node.Data != null)
                        {
                            //Only add new items, this is most likely to be run at login time before any inventory
                            //nodes other than the root are populated.
                            if (!Items.ContainsKey(node.Data.UUID))
                            {
                                Items.Add(node.Data.UUID, node);
                                node.Parent = pnode;                   //Update this node with its parent
                                pnode.Nodes.Add(node.Data.UUID, node); // Add to the parents child list
                                item_count++;
                            }
                        }

                        del_nodes.Add(node);
                    }
                }

                //Clean up processed nodes this loop around.
                foreach (InventoryNode node in del_nodes)
                {
                    nodes.Remove(node);
                }

                del_nodes.Clear();
            }

            Logger.Log("Reassembled " + item_count.ToString() + " items from inventory cache file", Helpers.LogLevel.Info);
        }