private void Free(Dictionary <string, List <int> > map)
        {
            if (map == null)
            {
                return;
            }

            foreach (var value in map.Values)
            {
                if (value == null)
                {
                    continue;
                }

                SharedPools.BigDefault <List <int> >().ClearAndFree(value);
            }

            SharedPools.StringIgnoreCaseDictionary <List <int> >().ClearAndFree(map);
        }
        private static Dictionary <string, List <int> > CreateIdentifierLocations(Document document, SyntaxNode root, CancellationToken cancellationToken)
        {
            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            var identifierMap = SharedPools.StringIgnoreCaseDictionary <List <int> >().AllocateAndClear();

            foreach (var token in root.DescendantTokens(descendIntoTrivia: true))
            {
                if (token.IsMissing || token.Span.Length == 0)
                {
                    continue;
                }

                if (syntaxFacts.IsIdentifier(token) || syntaxFacts.IsGlobalNamespaceKeyword(token))
                {
                    var valueText = token.ValueText;
                    identifierMap.GetOrAdd(valueText, _ => SharedPools.BigDefault <List <int> >().AllocateAndClear()).Add(token.Span.Start);
                }
            }

            return(identifierMap);
        }
        private bool WriteIdentifierLocations(int projectId, int documentId, Document document, VersionStamp version, SyntaxNode root, CancellationToken cancellationToken)
        {
            // delete any existing data
            if (!DeleteIdentifierLocations(projectId, documentId, cancellationToken))
            {
                return(false);
            }

            var identifierMap = SharedPools.StringIgnoreCaseDictionary <int>().AllocateAndClear();

            Dictionary <string, List <int> > map = null;

            try
            {
                map = CreateIdentifierLocations(document, root, cancellationToken);

                // okay, write new data
                using (var accessor = _esentStorage.GetIdentifierLocationTableAccessor())
                {
                    // make sure I have all identifier ready before starting big insertion
                    int identifierId;
                    foreach (var identifier in map.Keys)
                    {
                        if (!TryGetUniqueIdentifierId(identifier, out identifierId))
                        {
                            return(false);
                        }

                        identifierMap[identifier] = identifierId;
                    }

                    // save whole map
                    var uncommittedCount = 0;

                    foreach (var kv in map)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        var identifier = kv.Key;
                        var positions  = kv.Value;

                        if ((uncommittedCount + positions.Count) > FlushThreshold)
                        {
                            accessor.Flush();
                            uncommittedCount = 0;
                        }

                        accessor.PrepareBatchOneInsert();

                        identifierId = identifierMap[identifier];

                        using (var stream = accessor.GetBatchInsertStream(projectId, documentId, identifierId))
                            using (var writer = new ObjectWriter(stream, cancellationToken: cancellationToken))
                            {
                                writer.WriteString(IdentifierSetSerializationVersion);
                                WriteList(writer, positions);
                            }

                        accessor.FinishBatchOneInsert();

                        uncommittedCount += positions.Count;
                    }

                    // save special identifier that indicates version for this document
                    if (!TrySaveIdentifierSetVersion(accessor, projectId, documentId, version))
                    {
                        return(false);
                    }

                    return(accessor.ApplyChanges());
                }
            }
            finally
            {
                SharedPools.StringIgnoreCaseDictionary <int>().ClearAndFree(identifierMap);
                Free(map);
            }
        }