public EsentPersistentStorage(
            IOptionService optionService, string workingFolderPath, string solutionFilePath, Action <AbstractPersistentStorage> disposer) :
            base(optionService, workingFolderPath, solutionFilePath, disposer)
        {
            // cache delegates
            _readStreamSolution  = ReadStreamSolution;
            _readStream          = ReadStream;
            _writeStreamSolution = WriteStreamSolution;
            _writeStream         = WriteStream;

            // solution must exist in disk. otherwise, we shouldn't be here at all.
            Contract.ThrowIfTrue(string.IsNullOrWhiteSpace(solutionFilePath));

            var databaseFile = GetDatabaseFile(workingFolderPath);

            this.EsentDirectory = Path.GetDirectoryName(databaseFile);

            if (!Directory.Exists(this.EsentDirectory))
            {
                Directory.CreateDirectory(this.EsentDirectory);
            }

            _nameTableCache = new ConcurrentDictionary <string, int>(StringComparer.OrdinalIgnoreCase);

            var enablePerformanceMonitor = optionService.GetOption(InternalFeatureOnOffOptions.EsentPerformanceMonitor);

            _esentStorage = new EsentStorage(databaseFile, enablePerformanceMonitor);
        }
        private VersionStamp GetIdentifierSetVersion(EsentStorage.Key key, int identifierId, object unused1, object unused2, CancellationToken cancellationToken)
        {
            using (var accessor = _esentStorage.GetIdentifierLocationTableAccessor())
            using (var stream = accessor.GetReadStream(key, identifierId))
            {
                if (stream == null)
                {
                    return VersionStamp.Default;
                }

                using (var reader = new ObjectReader(stream))
                {
                    return VersionStamp.ReadFrom(reader);
                }
            }
        }
        private VersionStamp GetIdentifierSetVersion(EsentStorage.Key key)
        {
            if (!PersistenceEnabled)
            {
                return VersionStamp.Default;
            }

            int identifierId;
            if (!TryGetIdentifierSetVersionId(out identifierId))
            {
                return VersionStamp.Default;
            }

            // TODO: verify that project is in solution associated with the storage
            return EsentExceptionWrapper(key, identifierId, GetIdentifierSetVersion, CancellationToken.None);
        }
            public OpenSession(EsentStorage storage, string databaseFile, CancellationToken shutdownCancellationToken)
            {
                _storage = storage;

#if false
                id = Interlocked.Increment(ref globalId);
                System.Diagnostics.Trace.WriteLine("open sessionId: " + id);
#endif

                _session = new Session(storage._instance);

                _databaseFile = databaseFile;
                _databaseId = OpenExistingDatabase(_session, databaseFile);

                _shutdownCancellationToken = shutdownCancellationToken;
                _cancellationTokenRegistration = shutdownCancellationToken.Register(() => Dispose(), useSynchronizationContext: false);
            }
            public OpenSession(EsentStorage storage, string databaseFile, CancellationToken shutdownCancellationToken)
            {
                _storage = storage;

#if false
                id = Interlocked.Increment(ref globalId);
                System.Diagnostics.Trace.WriteLine("open sessionId: " + id);
#endif

                _session = new Session(storage._instance);

                _databaseFile = databaseFile;
                _databaseId   = OpenExistingDatabase(_session, databaseFile);

                _shutdownCancellationToken     = shutdownCancellationToken;
                _cancellationTokenRegistration = shutdownCancellationToken.Register(() => Dispose(), useSynchronizationContext: false);
            }
        private bool TrySaveIdentifierSetVersion(
            EsentStorage.IdentifierLocationTableAccessor accessor, int projectId, int documentId, VersionStamp version)
        {
            int identifierId;
            if (!TryGetIdentifierSetVersionId(out identifierId))
            {
                return false;
            }

            accessor.PrepareBatchOneInsert();
            using (var stream = accessor.GetBatchInsertStream(projectId, documentId, identifierId))
            using (var writer = new ObjectWriter(stream))
            {
                version.WriteTo(writer);
            }

            accessor.FinishBatchOneInsert();
            return true;
        }
        private bool WriteIdentifierLocations(EsentStorage.Key key, Document document, VersionStamp version, SyntaxNode root, CancellationToken cancellationToken)
        {
            // delete any existing data
            if (!DeleteIdentifierLocations(key, 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.GetWriteStream(key, 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, key, version))
                    {
                        return false;
                    }

                    return accessor.ApplyChanges();
                }
            }
            finally
            {
                SharedPools.StringIgnoreCaseDictionary<int>().ClearAndFree(identifierMap);
                Free(map);
            }
        }
 private bool DeleteIdentifierLocations(EsentStorage.Key key, CancellationToken cancellationToken)
 {
     using (var accessor = _esentStorage.GetIdentifierLocationTableAccessor())
     {
         accessor.Delete(key, cancellationToken);
         return accessor.ApplyChanges();
     }
 }
        private bool ReadIdentifierPositions(EsentStorage.Key key, int identifierId, List<int> positions, object unused, CancellationToken cancellationToken)
        {
            using (var accessor = _esentStorage.GetIdentifierLocationTableAccessor())
            using (var stream = accessor.GetReadStream(key, identifierId))
            {
                if (stream == null)
                {
                    // no such identifier exist.
                    return true;
                }

                using (var reader = new ObjectReader(stream))
                {
                    var formatVersion = reader.ReadString();
                    if (formatVersion != IdentifierSetSerializationVersion)
                    {
                        return false;
                    }

                    return ReadFrom(reader, positions, cancellationToken);
                }
            }
        }