public static void TransactionCommit()
        {
            var itself = _constants.Itself;

            var tempDatabaseFilename       = Path.GetTempFileName();
            var tempTransactionLogFilename = Path.GetTempFileName();

            // Commit
            using (var memoryAdapter = new UInt64LinksTransactionsLayer(new UInt64UnitedMemoryLinks(tempDatabaseFilename), tempTransactionLogFilename))
                using (var links = new UInt64Links(memoryAdapter))
                {
                    using (var transaction = memoryAdapter.BeginTransaction())
                    {
                        var l1 = links.CreateAndUpdate(itself, itself);
                        var l2 = links.CreateAndUpdate(itself, itself);

                        Global.Trash = links.Update(l2, l2, l1, l2);

                        links.Delete(l1);

                        transaction.Commit();
                    }

                    Global.Trash = links.Count();
                }

            Global.Trash = FileHelpers.ReadAll <UInt64LinksTransactionsLayer.Transition>(tempTransactionLogFilename);
        }
        public static void Bug1Test()
        {
            var tempDatabaseFilename       = Path.GetTempFileName();
            var tempTransactionLogFilename = Path.GetTempFileName();

            var itself = _constants.Itself;

            // User Code Error (Autoreverted), some data saved
            try
            {
                ulong l1;
                ulong l2;

                using (var memory = new UInt64UnitedMemoryLinks(tempDatabaseFilename))
                    using (var memoryAdapter = new UInt64LinksTransactionsLayer(memory, tempTransactionLogFilename))
                        using (var links = new UInt64Links(memoryAdapter))
                        {
                            l1 = links.CreateAndUpdate(itself, itself);
                            l2 = links.CreateAndUpdate(itself, itself);

                            l2 = links.Update(l2, l2, l1, l2);

                            links.CreateAndUpdate(l2, itself);
                            links.CreateAndUpdate(l2, itself);
                        }

                Global.Trash = FileHelpers.ReadAll <UInt64LinksTransactionsLayer.Transition>(tempTransactionLogFilename);

                using (var memory = new UInt64UnitedMemoryLinks(tempDatabaseFilename))
                    using (var memoryAdapter = new UInt64LinksTransactionsLayer(memory, tempTransactionLogFilename))
                        using (var links = new UInt64Links(memoryAdapter))
                        {
                            using (var transaction = memoryAdapter.BeginTransaction())
                            {
                                l2 = links.Update(l2, l1);

                                links.Delete(l2);

                                ExceptionThrower();

                                transaction.Commit();
                            }

                            Global.Trash = links.Count();
                        }
            }
            catch
            {
                Global.Trash = FileHelpers.ReadAll <UInt64LinksTransactionsLayer.Transition>(tempTransactionLogFilename);
            }

            File.Delete(tempDatabaseFilename);
            File.Delete(tempTransactionLogFilename);
        }
        public static void TransactionDamage()
        {
            var itself = _constants.Itself;

            var tempDatabaseFilename       = Path.GetTempFileName();
            var tempTransactionLogFilename = Path.GetTempFileName();

            // Commit
            using (var memoryAdapter = new UInt64LinksTransactionsLayer(new UInt64UnitedMemoryLinks(tempDatabaseFilename), tempTransactionLogFilename))
                using (var links = new UInt64Links(memoryAdapter))
                {
                    using (var transaction = memoryAdapter.BeginTransaction())
                    {
                        var l1 = links.CreateAndUpdate(itself, itself);
                        var l2 = links.CreateAndUpdate(itself, itself);

                        Global.Trash = links.Update(l2, l2, l1, l2);

                        links.Delete(l1);

                        transaction.Commit();
                    }

                    Global.Trash = links.Count();
                }

            Global.Trash = FileHelpers.ReadAll <UInt64LinksTransactionsLayer.Transition>(tempTransactionLogFilename);

            // Damage database

            FileHelpers.WriteFirst(tempTransactionLogFilename, new UInt64LinksTransactionsLayer.Transition(new UniqueTimestampFactory(), 555));

            // Try load damaged database
            try
            {
                // TODO: Fix
                using (var memoryAdapter = new UInt64LinksTransactionsLayer(new UInt64UnitedMemoryLinks(tempDatabaseFilename), tempTransactionLogFilename))
                    using (var links = new UInt64Links(memoryAdapter))
                    {
                        Global.Trash = links.Count();
                    }
            }
            catch (NotSupportedException ex)
            {
                Assert.True(ex.Message == "Database is damaged, autorecovery is not supported yet.");
            }

            Global.Trash = FileHelpers.ReadAll <UInt64LinksTransactionsLayer.Transition>(tempTransactionLogFilename);

            File.Delete(tempDatabaseFilename);
            File.Delete(tempTransactionLogFilename);
        }
        public static void SavedSequencesOptimizationTest()
        {
            LinksConstants <ulong> constants = new LinksConstants <ulong>((1, long.MaxValue), (long.MaxValue + 1UL, ulong.MaxValue));

            using (var memory = new HeapResizableDirectMemory())
                using (var disposableLinks = new UInt64UnitedMemoryLinks(memory, UInt64UnitedMemoryLinks.DefaultLinksSizeStep, constants, IndexTreeType.Default))
                {
                    var links = new UInt64Links(disposableLinks);

                    var root = links.CreatePoint();

                    //var numberToAddressConverter = new RawNumberToAddressConverter<ulong>();
                    var addressToNumberConverter = new AddressToRawNumberConverter <ulong>();

                    var unicodeSymbolMarker   = links.GetOrCreate(root, addressToNumberConverter.Convert(1));
                    var unicodeSequenceMarker = links.GetOrCreate(root, addressToNumberConverter.Convert(2));

                    var totalSequenceSymbolFrequencyCounter = new TotalSequenceSymbolFrequencyCounter <ulong>(links);
                    var linkFrequenciesCache = new LinkFrequenciesCache <ulong>(links, totalSequenceSymbolFrequencyCounter);
                    var index = new CachedFrequencyIncrementingSequenceIndex <ulong>(linkFrequenciesCache);
                    var linkToItsFrequencyNumberConverter        = new FrequenciesCacheBasedLinkToItsFrequencyNumberConverter <ulong>(linkFrequenciesCache);
                    var sequenceToItsLocalElementLevelsConverter = new SequenceToItsLocalElementLevelsConverter <ulong>(links, linkToItsFrequencyNumberConverter);
                    var optimalVariantConverter = new OptimalVariantConverter <ulong>(links, sequenceToItsLocalElementLevelsConverter);

                    var walker = new RightSequenceWalker <ulong>(links, new DefaultStack <ulong>(), (link) => constants.IsExternalReference(link) || links.IsPartialPoint(link));

                    var unicodeSequencesOptions = new SequencesOptions <ulong>()
                    {
                        UseSequenceMarker  = true,
                        SequenceMarkerLink = unicodeSequenceMarker,
                        UseIndex           = true,
                        Index = index,
                        LinksToSequenceConverter = optimalVariantConverter,
                        Walker = walker,
                        UseGarbageCollection = true
                    };

                    var unicodeSequences = new Sequences.Sequences(new SynchronizedLinks <ulong>(links), unicodeSequencesOptions);

                    // Create some sequences
                    var strings = _loremIpsumExample.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
                    var arrays  = strings.Select(x => x.Select(y => addressToNumberConverter.Convert(y)).ToArray()).ToArray();
                    for (int i = 0; i < arrays.Length; i++)
                    {
                        unicodeSequences.Create(arrays[i].ShiftRight());
                    }

                    var linksCountAfterCreation = links.Count();

                    // get list of sequences links
                    // for each sequence link
                    //   create new sequence version
                    //   if new sequence is not the same as sequence link
                    //     delete sequence link
                    //     collect garbadge
                    unicodeSequences.CompactAll();

                    var linksCountAfterCompactification = links.Count();

                    Assert.True(linksCountAfterCompactification < linksCountAfterCreation);
                }
        }