Exemplo n.º 1
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.º 2
0
        /// <summary>
        /// Do checkpoint operation to copy log pages into data file. Return how many transactions was commited inside data file
        /// Checkpoint requires exclusive lock database
        /// </summary>
        public int Checkpoint()
        {
            // no log file or no confirmed transaction, just exit
            if (_disk.GetLength(FileOrigin.Log) == 0 || _confirmTransactions.Count == 0)
            {
                return(0);
            }

            var mustExit = _locker.EnterExclusive();

            try
            {
                return(this.CheckpointInternal());
            }
            finally
            {
                if (mustExit)
                {
                    _locker.ExitExclusive();
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Do checkpoint operation to copy log pages into data file. Return how many transactions was commited inside data file
        /// If soft = true, just try enter in exclusive mode - if not possible, just exit
        /// </summary>
        public void Checkpoint(bool soft)
        {
            // get original log length
            var logLength = _disk.GetLength(FileOrigin.Log);

            // no log file or no confirmed transaction, just exit
            if (logLength == 0 || _confirmTransactions.Count == 0)
            {
                return;
            }

            // for safe, lock all database (read/write) before run checkpoint operation
            // future versions can be smarter and avoid lock (be more like SQLite checkpoint)
            if (soft)
            {
                // shutdown mode only try enter in exclusive mode... if not possible, exit without checkpoint
                if (_locker.TryEnterExclusive() == false)
                {
                    return;
                }
            }
            else
            {
                _locker.EnterReserved(true);
            }

            LOG($"checkpoint", "WAL");

            // wait all pages write on disk
            _disk.Queue.Wait();

            ENSURE(_disk.Queue.Length == 0, "no pages on queue when checkpoint");

            // getting all "good" pages from log file to be copied into data file
            IEnumerable <PageBuffer> source()
            {
                foreach (var buffer in _disk.ReadFull(FileOrigin.Log))
                {
                    // read direct from buffer to avoid create BasePage structure
                    var transactionID = buffer.ReadUInt32(BasePage.P_TRANSACTION_ID);

                    // only confied paged can be write on data disk
                    if (_confirmTransactions.Contains(transactionID))
                    {
                        var pageID = buffer.ReadUInt32(BasePage.P_PAGE_ID);

                        // clear isConfirmed/transactionID
                        buffer.Write(uint.MaxValue, BasePage.P_TRANSACTION_ID);
                        buffer.Write(false, BasePage.P_IS_CONFIRMED);

                        buffer.Position = BasePage.GetPagePosition(pageID);

                        yield return(buffer);
                    }
                }
            }

            // write all log pages into data file (sync)
            _disk.Write(source(), FileOrigin.Data);

            // reset
            _confirmTransactions.Clear();
            _index.Clear();

            _currentReadVersion = 0;

            // clear cache
            _disk.Cache.Clear();

            // clear log file (sync)
            _disk.SetLength(0, FileOrigin.Log);

            // remove exclusive lock
            _locker.ExitReserved(true);
        }