/// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="target">Target.</param>
        /// <param name="marsh">Marshaller.</param>
        /// <param name="cacheName">Cache name.</param>
        /// <param name="keepBinary">Binary flag.</param>
        public DataStreamerImpl(IPlatformTargetInternal target, Marshaller marsh, string cacheName, bool keepBinary)
            : base(target)
        {
            _cacheName  = cacheName;
            _keepBinary = keepBinary;

            // Create empty batch.
            _batch = new DataStreamerBatch <TK, TV>();

            // Allocate GC handle so that this data streamer could be easily dereferenced from native code.
            WeakReference thisRef = new WeakReference(this);

            _hnd = marsh.Ignite.HandleRegistry.Allocate(thisRef);

            // Start topology listening. This call will ensure that buffer size member is updated.
            DoOutInOp(OpListenTopology, _hnd);

            // Membar to ensure fields initialization before leaving constructor.
            Thread.MemoryBarrier();

            // Start flusher after everything else is initialized.
            _flusher = new Flusher <TK, TV>(thisRef);

            _flusher.RunThread();
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="prev">Previous batch.</param>
        public DataStreamerBatch(DataStreamerBatch <TK, TV> prev)
        {
            _prev = prev;

            if (prev != null)
            {
                Thread.MemoryBarrier(); // Prevent "prev" field escape.
            }
            _fut.Task.ContWith(x => ParentsCompleted());
        }
示例#3
0
        /** <inheritDoc /> */
        public void TryFlush()
        {
            ThrowIfDisposed();

            DataStreamerBatch <TK, TV> batch0 = _batch;

            if (batch0 != null)
            {
                Flush0(batch0, false, PlcFlush);
            }
        }
示例#4
0
        /** <inheritDoc /> */
        public void Flush()
        {
            ThrowIfDisposed();

            DataStreamerBatch <TK, TV> batch0 = _batch;

            if (batch0 != null)
            {
                Flush0(batch0, true, PlcFlush);
            }
            else
            {
                // Batch is null, i.e. data streamer is closing. Wait for close to complete.
                _closedEvt.Wait();
            }
        }
        /** <inheritDoc /> */
        public void Close(bool cancel)
        {
            _flusher.Stop();

            while (true)
            {
                DataStreamerBatch <TK, TV> batch0 = _batch;

                if (batch0 == null)
                {
                    // Wait for concurrent close to finish.
                    _closeFut.Task.Wait();
                    return;
                }

                _rwLock.EnterWriteLock();

                try
                {
                    if (!Flush0(batch0, true, cancel ? PlcCancelClose : PlcClose))
                    {
                        // Retry flushing.
                        continue;
                    }

                    base.Dispose(true);
                    ReleaseHandles();
                    ThreadPool.QueueUserWorkItem(_ => _closeFut.TrySetResult(null));

                    return;
                }
                catch (Exception e)
                {
                    base.Dispose(true);
                    ReleaseHandles();
                    ThreadPool.QueueUserWorkItem(_ => _closeFut.TrySetException(e));

                    throw;
                }
                finally
                {
                    _rwLock.ExitWriteLock();
                }
            }
        }
        /// <summary>
        /// Checck whether all previous batches are completed.
        /// </summary>
        /// <returns></returns>
        private bool ParentsCompleted()
        {
            DataStreamerBatch <TK, TV> prev0 = _prev;

            if (prev0 != null)
            {
                if (prev0.ParentsCompleted())
                {
                    _prev = null;
                }
                else
                {
                    return(false);
                }
            }

            return(_fut.Task.IsCompleted);
        }
示例#7
0
        /// <summary>
        /// Internal flush routine.
        /// </summary>
        /// <param name="curBatch"></param>
        /// <param name="wait">Whether to wait for flush to complete.</param>
        /// <param name="plc">Whether this is the last batch.</param>
        /// <returns>Whether this call was able to CAS previous batch</returns>
        private bool Flush0(DataStreamerBatch <TK, TV> curBatch, bool wait, int plc)
        {
            // 1. Try setting new current batch to help further adders.
            bool res = Interlocked.CompareExchange(ref _batch,
                                                   (plc == PlcContinue || plc == PlcFlush) ?
                                                   new DataStreamerBatch <TK, TV>(curBatch) : null, curBatch) == curBatch;

            // 2. Perform actual send.
            curBatch.Send(this, plc);

            if (wait)
            {
                // 3. Wait for all futures to finish.
                curBatch.AwaitCompletion();
            }

            return(res);
        }
示例#8
0
        public void AwaitCompletion()
        {
            DataStreamerBatch <TK, TV> curBatch = this;

            while (curBatch != null)
            {
                try
                {
                    curBatch._fut.Get();
                }
                catch (Exception)
                {
                    // Ignore.
                }

                curBatch = curBatch._prev;
            }
        }
示例#9
0
        /** <inheritDoc /> */
        public void Close(bool cancel)
        {
            _flusher.Stop();

            while (true)
            {
                DataStreamerBatch <TK, TV> batch0 = _batch;

                if (batch0 == null)
                {
                    // Wait for concurrent close to finish.
                    _closedEvt.Wait();

                    return;
                }

                if (Flush0(batch0, true, cancel ? PlcCancelClose : PlcClose))
                {
                    _closeFut.OnDone(null, null);

                    _rwLock.EnterWriteLock();

                    try
                    {
                        base.Dispose(true);

                        if (_rcv != null)
                        {
                            Marshaller.Ignite.HandleRegistry.Release(_rcvHnd);
                        }

                        _closedEvt.Set();
                    }
                    finally
                    {
                        _rwLock.ExitWriteLock();
                    }

                    Marshaller.Ignite.HandleRegistry.Release(_hnd);

                    break;
                }
            }
        }
示例#10
0
        public void AwaitCompletion()
        {
            DataStreamerBatch <TK, TV> curBatch = this;

            while (curBatch != null)
            {
                try
                {
                    curBatch._fut.Get();
                }
                // ReSharper disable once EmptyGeneralCatchClause
                catch (Exception)
                {
                    // Ignore.
                }

                curBatch = curBatch._prev;
            }
        }
        /// <summary>
        /// Internal send routine.
        /// </summary>
        /// <param name="ldr">streamer.</param>
        /// <param name="plc">Policy.</param>
        public void Send(DataStreamerImpl <TK, TV> ldr, int plc)
        {
            // 1. Delegate to the previous batch first.
            DataStreamerBatch <TK, TV> prev0 = _prev;

            if (prev0 != null)
            {
                prev0.Send(ldr, DataStreamerImpl <TK, TV> .PlcContinue);
            }

            // 2. Set guard.
            _rwLock.EnterWriteLock();

            try
            {
                if (_sndGuard)
                {
                    return;
                }
                else
                {
                    _sndGuard = true;
                }
            }
            finally
            {
                _rwLock.ExitWriteLock();
            }

            var handleRegistry = ldr.Marshaller.Ignite.HandleRegistry;

            long futHnd = 0;

            // 3. Actual send.
            try
            {
                ldr.Update(writer =>
                {
                    writer.WriteInt(plc);

                    if (plc != DataStreamerImpl <TK, TV> .PlcCancelClose)
                    {
                        futHnd = handleRegistry.Allocate(_fut);

                        writer.WriteLong(futHnd);

                        WriteTo(writer);
                    }
                });
            }
            catch (Exception)
            {
                if (futHnd != 0)
                {
                    handleRegistry.Release(futHnd);
                }

                throw;
            }

            if (plc == DataStreamerImpl <TK, TV> .PlcCancelClose || _size == 0)
            {
                ThreadPool.QueueUserWorkItem(_ => _fut.OnNullResult());

                handleRegistry.Release(futHnd);
            }
        }