Example #1
0
        private void WriteCurrentFragmentAndReset()
        {
            // log trace of the fragment
            PSEtwLog.LogAnalyticVerbose(
                PSEventId.SentRemotingFragment, PSOpcode.Send, PSTask.None,
                PSKeyword.Transport | PSKeyword.UseAlwaysAnalytic,
                (Int64)(_currentFragment.ObjectId),
                (Int64)(_currentFragment.FragmentId),
                _currentFragment.IsStartFragment ? 1 : 0,
                _currentFragment.IsEndFragment ? 1 : 0,
                (UInt32)(_currentFragment.BlobLength),
                new PSETWBinaryBlob(_currentFragment.Blob, 0, _currentFragment.BlobLength));

            // finally write into memory stream
            byte[] data             = _currentFragment.GetBytes();
            int    amountLeft       = data.Length;
            int    offSetToReadFrom = 0;

            // user asked us to notify immediately..so no need
            // to write into memory stream..instead give the
            // data directly to user and let him figure out what to do.
            // This will save write + read + dispose!!
            if (!_notifyOnWriteFragmentImmediately)
            {
                lock (_syncObject)
                {
                    // technically this should throw an exception..but remoting callstack
                    // is optimized ie., we are not locking in every layer (in powershell)
                    // to save on performance..as a result there may be cases where
                    // upper layer is trying to add stuff and stream is disposed while
                    // adding stuff.
                    if (_isDisposed)
                    {
                        return;
                    }

                    if (_writeStream == null)
                    {
                        _writeStream = new MemoryStream(_fragmentSize);
                        s_trace.WriteLine("Created write stream: {0}", _writeStream.GetHashCode());
                        _writeOffset = 0;
                    }

                    while (amountLeft > 0)
                    {
                        int dataLeftInWriteStream = _writeStream.Capacity - _writeOffset;
                        if (dataLeftInWriteStream == 0)
                        {
                            // enqueue the current write stream and create a new one.
                            EnqueueWriteStream();
                            dataLeftInWriteStream = _writeStream.Capacity - _writeOffset;
                        }

                        int amountToWriteIntoStream = (amountLeft > dataLeftInWriteStream) ? dataLeftInWriteStream : amountLeft;
                        amountLeft -= amountToWriteIntoStream;
                        // write data
                        _writeStream.Position = _writeOffset;
                        _writeStream.Write(data, offSetToReadFrom, amountToWriteIntoStream);
                        offSetToReadFrom += amountToWriteIntoStream;
                        _writeOffset     += amountToWriteIntoStream;
                        _length          += amountToWriteIntoStream;
                    }
                }
            }

            // call the callback since we have data available
            _onDataAvailableCallback?.Invoke(data, _currentFragment.IsEndFragment);

            // prepare a new fragment
            _currentFragment.FragmentId      = ++_fragmentId;
            _currentFragment.IsStartFragment = false;
            _currentFragment.IsEndFragment   = false;
            _currentFragment.BlobLength      = 0;
            _currentFragment.Blob            = new byte[_fragmentSize];
        }