Exemplo n.º 1
0
        /// <summary>
        /// Load all confirmed transactions from log file (used only when open datafile)
        /// Don't need lock because it's called on ctor of LiteEngine
        /// </summary>
        public void RestoreIndex(ref HeaderPage header)
        {
            // get all page positions
            var positions = new Dictionary <long, List <PagePosition> >();
            var current   = 0L;

            // read all pages to get confirmed transactions (do not read page content, only page header)
            foreach (var buffer in _disk.ReadFull(FileOrigin.Log))
            {
                // read direct from buffer to avoid create BasePage structure
                var pageID        = buffer.ReadUInt32(BasePage.P_PAGE_ID);
                var isConfirmed   = buffer.ReadBool(BasePage.P_IS_CONFIRMED);
                var transactionID = buffer.ReadUInt32(BasePage.P_TRANSACTION_ID);

                var position = new PagePosition(pageID, current);

                if (positions.TryGetValue(transactionID, out var list))
                {
                    list.Add(position);
                }
                else
                {
                    positions[transactionID] = new List <PagePosition> {
                        position
                    };
                }

                if (isConfirmed)
                {
                    this.ConfirmTransaction(transactionID, positions[transactionID]);

                    var pageType = (PageType)buffer.ReadByte(BasePage.P_PAGE_TYPE);

                    // when a header is modified in transaction, must always be the last page inside log file (per transaction)
                    if (pageType == PageType.Header)
                    {
                        // page buffer instance can't change
                        var headerBuffer = header.Buffer;

                        // copy this buffer block into original header block
                        Buffer.BlockCopy(buffer.Array, buffer.Offset, headerBuffer.Array, headerBuffer.Offset, PAGE_SIZE);

                        // re-load header (using new buffer data)
                        header = new HeaderPage(headerBuffer);
                        header.TransactionID = uint.MaxValue;
                        header.IsConfirmed   = false;
                    }
                }

                // update last transaction ID
                _lastTransactionID = (int)transactionID;

                current += PAGE_SIZE;
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Initialize LiteEngine using initial engine settings
        /// </summary>
        public LiteEngine(EngineSettings settings)
        {
            _settings = settings ?? throw new ArgumentNullException(nameof(settings));

            // clear checkpoint if database is readonly
            if (_settings.ReadOnly)
            {
                _settings.Checkpoint = 0;
            }

            LOG($"start initializing{(_settings.ReadOnly ? " (readonly)" : "")}", "ENGINE");

            try
            {
                // initialize locker service (no dependency)
                _locker = new LockService(settings.Timeout, settings.ReadOnly);

                // initialize disk service (will create database if needed)
                _disk = new DiskService(settings);

                // read page with no cache ref (has a own PageBuffer) - do not Release() support
                var buffer = _disk.ReadFull(FileOrigin.Data).First();

                // if first byte are 1 this datafile are encrypted but has do defined password to open
                if (buffer[0] == 1)
                {
                    throw new LiteException(0, "This data file is encrypted and needs a password to open");
                }

                _header = new HeaderPage(buffer);

                // initialize wal-index service
                _walIndex = new WalIndexService(_disk, _locker);

                // if exists log file, restore wal index references (can update full _header instance)
                if (_disk.GetLength(FileOrigin.Log) > 0)
                {
                    _walIndex.RestoreIndex(ref _header);
                }

                // initialize sort temp disk
                _sortDisk = new SortDisk(settings.CreateTempFactory(), CONTAINER_SORT_SIZE, settings.UtcDate);

                // initialize transaction monitor as last service
                _monitor = new TransactionMonitor(_header, _locker, _disk, _walIndex, _settings);

                // register system collections
                this.InitializeSystemCollections();

                LOG("initialization completed", "ENGINE");
            }
            catch (Exception ex)
            {
                LOG(ex.Message, "ERROR");

                // explicit dispose (but do not run shutdown operation)
                this.Dispose(true);
                throw;
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Get all pages from datafile based only in Page Position (get from disk - not from cache)
        /// </summary>
        private IEnumerable <BsonDocument> DumpPages()
        {
            var collections = _header.GetCollections().ToDictionary(x => x.Value, x => x.Key);

            foreach (var buffer in _disk.ReadFull())
            {
                var page = new BasePage(buffer);

                var doc = new BsonDocument
                {
                    ["position"] = Number(buffer.Position),
                    ["origin"]   = page.PageID == 0 && page.TransactionID == 0 && page.PageType == PageType.Empty ? "blank" :
                                   buffer.Position < _disk.LogStartPosition ? "data" : "log",

                    ["pageID"]     = (int)page.PageID,
                    ["pageType"]   = page.PageType.ToString(),
                    ["nextPageID"] = (int)page.NextPageID,
                    ["prevPageID"] = (int)page.PrevPageID,
                    ["collection"] = collections.GetOrDefault(page.ColID, "-"),

                    ["transactionID"] = (int)page.TransactionID,
                    ["isConfirmed"]   = page.IsConfirmed,

                    ["itemsCount"]       = (int)page.ItemsCount,
                    ["freeBytes"]        = page.FreeBytes,
                    ["usedBytes"]        = (int)page.UsedBytes,
                    ["fragmentedBytes"]  = (int)page.FragmentedBytes,
                    ["nextFreePosition"] = (int)page.NextFreePosition,
                    ["highestIndex"]     = (int)page.HighestIndex
                };

                yield return(doc);
            }
        }