Exemple #1
0
        public void OnDeleteTopic(Topic topic, IDObjects.NumberSet linksAffected, CodeDB.EventAccessor eventAccessor)
        {
            if (!IncludeInIndex(topic))
            {
                return;
            }

            TopicEntry entry = new TopicEntry(topic, this);

            accessLock.EnterWriteLock();

            try
            {
                foreach (string keyword in entry.Keywords)
                {
                    string prefix    = KeywordPrefix(keyword);
                    var    numberSet = prefixTopicIDs[prefix];

                    if (numberSet != null)
                    {
                        numberSet.Remove(topic.TopicID);

                        if (numberSet.IsEmpty)
                        {
                            prefixTopicIDs.Remove(prefix);

                            foreach (var changeWatcher in changeWatchers)
                            {
                                changeWatcher.OnDeletePrefix(prefix, eventAccessor);
                            }
                        }
                        else
                        {
                            foreach (var changeWatcher in changeWatchers)
                            {
                                changeWatcher.OnUpdatePrefix(prefix, eventAccessor);
                            }
                        }
                    }
                }
            }
            finally
            { accessLock.ExitWriteLock(); }
        }
Exemple #2
0
        // Group: CodeDB.IChangeWatcher Functions
        // __________________________________________________________________________


        public void OnAddTopic(Topic topic, CodeDB.EventAccessor eventAccessor)
        {
            if (!IncludeInIndex(topic))
            {
                return;
            }

            TopicEntry entry = new TopicEntry(topic, this);

            accessLock.EnterWriteLock();

            try
            {
                foreach (string keyword in entry.Keywords)
                {
                    string prefix   = KeywordPrefix(keyword);
                    var    topicIDs = prefixTopicIDs[prefix];

                    if (topicIDs == null)
                    {
                        topicIDs = new IDObjects.NumberSet();
                        topicIDs.Add(topic.TopicID);
                        prefixTopicIDs[prefix] = topicIDs;

                        foreach (var changeWatcher in changeWatchers)
                        {
                            changeWatcher.OnAddPrefix(prefix, eventAccessor);
                        }
                    }
                    else
                    {
                        topicIDs.Add(topic.TopicID);

                        foreach (var changeWatcher in changeWatchers)
                        {
                            changeWatcher.OnUpdatePrefix(prefix, eventAccessor);
                        }
                    }
                }
            }
            finally
            { accessLock.ExitWriteLock(); }
        }
Exemple #3
0
        public void OnUpdateTopic(Topic oldTopic, Topic newTopic, Topic.ChangeFlags changeFlags, CodeDB.EventAccessor eventAccessor)
        {
                        #if DEBUG
            if (IncludeInIndex(newTopic) != IncludeInIndex(oldTopic))
            {
                throw new Exception("SearchIndex incorrectly assumes IncludeInIndex() will be the same for both the old and new topics in OnUpdateTopic().");
            }
                        #endif

            if (!IncludeInIndex(newTopic))
            {
                return;
            }

            if ((changeFlags & (Topic.ChangeFlags.Title | Topic.ChangeFlags.CommentTypeID | Topic.ChangeFlags.SymbolDefinitonNumber |
                                Topic.ChangeFlags.Symbol | Topic.ChangeFlags.LanguageID | Topic.ChangeFlags.FileID |
                                Topic.ChangeFlags.EffectiveAccessLevel | Topic.ChangeFlags.Class)) == 0)
            {
                return;
            }


            // We assume that if the topics are similar enough to use OnUpdateTopic() instead of OnAdd/RemoveTopic() then they'll generate the exact
            // same keyword list, and they'll even be in the same order.  This allows for a nice optimization here, but test it in debug builds in case these
            // assumptions are wrong in the future.

                        #if DEBUG
            if (newTopic.TopicID != oldTopic.TopicID)
            {
                throw new Exception("SearchIndex incorrectly assumes both the old and new topics in OnUpdateTopic() have the same topic IDs.");
            }

            TopicEntry newEntry = new TopicEntry(newTopic, this);
            TopicEntry oldEntry = new TopicEntry(oldTopic, this);

            if (newEntry.Keywords.Count != oldEntry.Keywords.Count)
            {
                throw new Exception("SearchIndex incorrectly assumes both the old and new topics in OnUpdateTopic() have the same keywords.");
            }

            for (int i = 0; i < newEntry.Keywords.Count; i++)
            {
                if (newEntry.Keywords[i] != oldEntry.Keywords[i])
                {
                    throw new Exception("SearchIndex incorrectly assumes both the old and new topics in OnUpdateTopic() have the same keywords.");
                }
            }
                        #endif

            TopicEntry entry = new TopicEntry(newTopic, this);

            // We use upgradeable in case one of the change handlers needs to do something that requires a write lock.
            accessLock.EnterUpgradeableReadLock();

            try
            {
                foreach (var keyword in entry.Keywords)
                {
                    string prefix = KeywordPrefix(keyword);

                    foreach (var changeWatcher in changeWatchers)
                    {
                        changeWatcher.OnUpdatePrefix(prefix, eventAccessor);
                    }
                }
            }
            finally
            {
                // We don't have to test to see if it was upgraded because if it was the write lock should have been released
                // by the change handler and we should recursively be back to an upgradeable read lock.
                accessLock.ExitUpgradeableReadLock();
            }
        }
Exemple #4
0
        /* Function: GetKeywordEntries
         * Returns a list of all the <KeywordEntries> for a prefix, complete with all their <TopicEntries>.  If there are none it will return
         * null.  The returned list will not be in any particular order, it is up to the calling code to sort them as desired.
         */
        public List <KeywordEntry> GetKeywordEntries(string prefix, CodeDB.Accessor accessor, CancelDelegate cancelDelegate)
        {
            // Retrieve the topics from the database

            IDObjects.NumberSet topicIDs = PrefixTopicIDs(prefix);

            if (topicIDs == null || topicIDs.IsEmpty)
            {
                return(null);
            }

            List <Topic> topics        = null;
            bool         releaseDBLock = false;

            if (accessor.LockHeld == CodeDB.Accessor.LockType.None)
            {
                accessor.GetReadOnlyLock();
                releaseDBLock = true;
            }

            try
            {
                // Need to lookup class strings to be able to build hash paths
                topics = accessor.GetTopicsByID(topicIDs, cancelDelegate, CodeDB.Accessor.GetTopicFlags.BodyLengthOnly |
                                                CodeDB.Accessor.GetTopicFlags.DontLookupContexts |
                                                CodeDB.Accessor.GetTopicFlags.DontIncludeSummary |
                                                CodeDB.Accessor.GetTopicFlags.DontIncludePrototype);
            }
            finally
            {
                if (releaseDBLock)
                {
                    accessor.ReleaseLock();
                }
            }

            if (cancelDelegate())
            {
                return(null);
            }


            // Convert the topics into entries

            StringTable <KeywordEntry> keywordEntryTable = new StringTable <KeywordEntry>(KeySettings.IgnoreCase);

            foreach (var topic in topics)
            {
                TopicEntry topicEntry = new TopicEntry(topic, this);

                foreach (var keyword in topicEntry.Keywords)
                {
                    if (KeywordMatchesPrefix(keyword, prefix))
                    {
                        var keywordEntry = keywordEntryTable[keyword];

                        if (keywordEntry == null)
                        {
                            keywordEntry = new KeywordEntry(keyword);
                            keywordEntryTable[keyword] = keywordEntry;
                        }
                        else if (keywordEntry.Keyword != keyword)
                        {
                            // If they differ in case we still want to combine them, but we have to choose which case will be in the
                            // results.  Prioritize in this order: mixed case ('m'), all lowercase ('l'), all uppercase ('u').

                            char keywordCase, keywordEntryCase;

                            if (keyword == keyword.ToLower())
                            {
                                keywordCase = 'l';
                            }
                            else if (keyword == keyword.ToUpper())
                            {
                                keywordCase = 'u';
                            }
                            else
                            {
                                keywordCase = 'm';
                            }

                            if (keywordEntry.Keyword == keywordEntry.Keyword.ToLower())
                            {
                                keywordEntryCase = 'l';
                            }
                            else if (keywordEntry.Keyword == keywordEntry.Keyword.ToUpper())
                            {
                                keywordEntryCase = 'u';
                            }
                            else
                            {
                                keywordEntryCase = 'm';
                            }

                            if ((keywordCase == 'm' && keywordEntryCase != 'm') ||
                                (keywordCase == 'l' && keywordEntryCase == 'u'))
                            {
                                keywordEntry.Keyword = keyword;
                            }
                            else if (keywordCase == 'm' && keywordEntryCase == 'm')
                            {
                                // If they're both mixed, use the sort order.  This lets SomeValue be used instead of someValue.
                                if (string.Compare(keyword, keywordEntry.Keyword) > 0)
                                {
                                    keywordEntry.Keyword = keyword;
                                }
                            }
                        }

                        keywordEntry.TopicEntries.Add(topicEntry);
                    }
                }
            }

            List <KeywordEntry> keywordEntries = new List <KeywordEntry>(keywordEntryTable.Count);

            foreach (var keywordEntryTablePair in keywordEntryTable)
            {
                keywordEntries.Add(keywordEntryTablePair.Value);
            }


            return(keywordEntries);
        }