Ejemplo n.º 1
0
        /// <summary>
        /// Dispose stream readers and exit collection lock
        /// </summary>
        public void Dispose()
        {
            // release all data/index pages
            this.Clear();

            // release collection page (in read mode)
            if (_mode == LockMode.Read && _collectionPage != null)
            {
                _collectionPage.Buffer.Release();
            }

            if (_mode == LockMode.Read)
            {
                _locker.ExitRead(_collectionName);
            }
            else if (_mode == LockMode.Write)
            {
                _locker.ExitReserved(_collectionName);
            }
        }
Ejemplo n.º 2
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);
        }