示例#1
0
        /// <summary>
        /// Do checkpoint operation to copy log pages into data file. Return how many pages as saved into data file
        /// Soft checkpoint try execute only if there is no one using (try exclusive lock - if not possible just exit)
        /// If crop = true, reduce data file removing all log area. If not, keeps file with same size and clean all isConfirmed pages
        /// </summary>
        public async Task <int> Checkpoint()
        {
            LOG($"checkpoint", "WAL");

            var counter = 0;

            // getting all "good" pages from log file to be copied into data file
            async IAsyncEnumerable <PageBuffer> source()
            {
                // collect all isConfirmedPages
                var confirmedPages    = new List <long>();
                var finalDataPosition = (_disk.Header.LastPageID + 1) * PAGE_SIZE;

                await foreach (var buffer in _disk.ReadLog(false))
                {
                    // read direct from buffer to avoid create BasePage structure
                    var transactionID = buffer.ReadUInt32(BasePage.P_TRANSACTION_ID);

                    // only confirmed pages can be write on data disk
                    if (_confirmTransactions.Contains(transactionID))
                    {
                        // if page is confirmed page and are after data area, add to list
                        var isConfirmed = buffer.ReadBool(BasePage.P_IS_CONFIRMED);

                        if (isConfirmed && buffer.Position >= finalDataPosition)
                        {
                            confirmedPages.Add(buffer.Position);
                        }

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

                        // update buffer position to data area position
                        var pageID = buffer.ReadUInt32(BasePage.P_PAGE_ID);

                        buffer.Position = BasePage.GetPagePosition(pageID);

                        counter++;

                        yield return(buffer);
                    }
                }
            }

            // write all log pages into data file (sync)
            await _disk.WriteDataPages(source());

            // clear log file, clear wal index, memory cache,
            _confirmTransactions.Clear();
            _index.Clear();

            _lastTransactionID  = 0;
            _currentReadVersion = 0;

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

            _disk.ResetLogPosition(true);

            return(counter);
        }