Ejemplo n.º 1
0
        public Snapshot(LockMode mode, string collectionName, HeaderPage header, uint transactionID, TransactionPages transPages, LockService locker, WalIndexService walIndex, DiskReader reader, bool addIfNotExists)
        {
            _mode           = mode;
            _collectionName = collectionName;
            _header         = header;
            _transactionID  = transactionID;
            _transPages     = transPages;
            _locker         = locker;
            _walIndex       = walIndex;
            _reader         = reader;

            // enter in lock mode according initial mode
            if (mode == LockMode.Read)
            {
                _locker.EnterRead(_collectionName);
            }
            else
            {
                _locker.EnterReserved(_collectionName);
            }

            // get lastest read version from wal-index
            _readVersion = _walIndex.CurrentReadVersion;

            var srv = new CollectionService(_header, this, _transPages);

            // read collection (create if new - load virtual too)
            srv.Get(_collectionName, addIfNotExists, ref _collectionPage);

            // clear local pages (will clear _collectionPage link reference)
            if (_collectionPage != null)
            {
                _localPages.Remove(_collectionPage.PageID);
            }
        }
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);
        }