예제 #1
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="beginAddress"></param>
        /// <param name="endAddress"></param>
        /// <param name="scanBufferingMode"></param>
        /// <param name="epoch"></param>
        /// <param name="logPageSizeBits"></param>
        /// <param name="initForReads"></param>
        public unsafe ScanIteratorBase(long beginAddress, long endAddress, ScanBufferingMode scanBufferingMode, LightEpoch epoch, int logPageSizeBits, bool initForReads = true)
        {
            // If we are protected when creating the iterator, we do not need per-GetNext protection
            if (epoch != null && !epoch.ThisInstanceProtected())
            {
                this.epoch = epoch;
            }

            this.beginAddress    = beginAddress;
            this.endAddress      = endAddress;
            this.logPageSizeBits = logPageSizeBits;

            currentAddress = -1;
            nextAddress    = beginAddress;

            if (scanBufferingMode == ScanBufferingMode.SinglePageBuffering)
            {
                frameSize = 1;
            }
            else if (scanBufferingMode == ScanBufferingMode.DoublePageBuffering)
            {
                frameSize = 2;
            }
            else if (scanBufferingMode == ScanBufferingMode.NoBuffering)
            {
                frameSize = 0;
                return;
            }
            if (initForReads)
            {
                InitializeForReads();
            }
        }
예제 #2
0
        /// <summary>
        ///     Attempts to advance the version to the target version, executing the given action in a critical section
        ///     where no batches are being processed before entering the next version. Each version will be advanced to
        ///     exactly once. This method may fail and return false if given target version is not larger than the
        ///     current version (possibly due to concurrent invocations to advance to the same version).
        ///     After the method returns, subsequent calls to Version() and Enter() will return at least the value of
        ///     targetVersion.
        /// </summary>
        /// <param name="criticalSection"> The logic to execute in a critical section </param>
        /// <param name="targetVersion"> The version to advance to, or -1 for the immediate next version</param>
        /// <returns> Whether the advance was successful </returns>
        public bool TryAdvanceVersion(Action <long, long> criticalSection, long targetVersion = -1)
        {
            var ev = new ManualResetEventSlim();

            // Compare and exchange to install our advance
            while (Interlocked.CompareExchange(ref versionChanged, ev, null) != null)
            {
            }

            if (targetVersion != -1 && targetVersion <= version)
            {
                versionChanged.Set();
                versionChanged = null;
                return(false);
            }

            // Any thread that sees ev will be in v + 1, because the bump happens only after ev is set.
            var original = Interlocked.Read(ref version);

            epoch.BumpCurrentEpoch(() =>
            {
                version = targetVersion == -1 ? original + 1 : targetVersion;
                criticalSection(original, version);
                versionChanged.Set();
                versionChanged = null;
            });

            // Make sure that even if we are the only thread, we are able to make progress
            if (!epoch.ThisInstanceProtected())
            {
                epoch.Resume();
                epoch.Suspend();
            }
            return(true);
        }
예제 #3
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="hlog"></param>
        /// <param name="beginAddress"></param>
        /// <param name="endAddress"></param>
        /// <param name="scanBufferingMode"></param>
        /// <param name="epoch"></param>
        public unsafe GenericScanIterator(GenericAllocator <Key, Value> hlog, long beginAddress, long endAddress, ScanBufferingMode scanBufferingMode, LightEpoch epoch)
        {
            this.hlog = hlog;

            // If we are protected when creating the iterator, we do not need per-GetNext protection
            if (!epoch.ThisInstanceProtected())
            {
                this.epoch = epoch;
            }

            if (beginAddress == 0)
            {
                beginAddress = hlog.GetFirstValidLogicalAddress(0);
            }

            this.endAddress = endAddress;

            recordSize     = hlog.GetRecordSize(0).Item2;
            currentAddress = -1;
            nextAddress    = beginAddress;

            if (scanBufferingMode == ScanBufferingMode.SinglePageBuffering)
            {
                frameSize = 1;
            }
            else if (scanBufferingMode == ScanBufferingMode.DoublePageBuffering)
            {
                frameSize = 2;
            }
            else if (scanBufferingMode == ScanBufferingMode.NoBuffering)
            {
                frameSize = 0;
                return;
            }

            frame  = new GenericFrame <Key, Value>(frameSize, hlog.PageSize);
            loaded = new CountdownEvent[frameSize];

            // Only load addresses flushed to disk
            if (nextAddress < hlog.HeadAddress)
            {
                var frameNumber = (nextAddress >> hlog.LogPageSizeBits) % frameSize;
                hlog.AsyncReadPagesFromDeviceToFrame
                    (nextAddress >> hlog.LogPageSizeBits,
                    1, endAddress, AsyncReadPagesCallback, Empty.Default,
                    frame, out loaded[frameNumber]);
            }
        }
예제 #4
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="beginAddress"></param>
        /// <param name="endAddress"></param>
        /// <param name="scanBufferingMode"></param>
        /// <param name="epoch"></param>
        /// <param name="logPageSizeBits"></param>
        public unsafe ScanIteratorBase(long beginAddress, long endAddress, ScanBufferingMode scanBufferingMode, LightEpoch epoch, int logPageSizeBits)
        {
            // If we are protected when creating the iterator, we do not need per-GetNext protection
            if (!epoch.ThisInstanceProtected())
            {
                this.epoch = epoch;
            }

            this.beginAddress    = beginAddress;
            this.endAddress      = endAddress;
            this.logPageSizeBits = logPageSizeBits;

            currentAddress = -1;
            nextAddress    = beginAddress;

            if (scanBufferingMode == ScanBufferingMode.SinglePageBuffering)
            {
                frameSize = 1;
            }
            else if (scanBufferingMode == ScanBufferingMode.DoublePageBuffering)
            {
                frameSize = 2;
            }
            else if (scanBufferingMode == ScanBufferingMode.NoBuffering)
            {
                frameSize = 0;
                return;
            }

            loaded         = new CountdownEvent[frameSize];
            loadedCancel   = new CancellationTokenSource[frameSize];
            loadedPage     = new long[frameSize];
            nextLoadedPage = new long[frameSize];
            for (int i = 0; i < frameSize; i++)
            {
                loadedPage[i]     = -1;
                nextLoadedPage[i] = -1;
                loadedCancel[i]   = new CancellationTokenSource();
            }
        }