Exemplo n.º 1
0
        private static void Test(string[] args)
        {
            var    sbb = new StreamBlobDatabase(false, 1024, Test_BufferManage);
            Random r   = new Random(0);

            byte[] temp   = new byte[1024];
            int    trials = 0;

            for (;;)
            {
                int len = r.Next(1024) + 1;
                if (r.Next(100) == 0)
                {
                    len = 1024;
                }

                ArraySegment <byte> seg = new ArraySegment <byte>(temp, 0, len);
                Console.WriteLine("{0} - {1}", trials, seg.Count);
                if (seg.Count == 1024)
                {
                    Console.Write("*************************");
                }

                trials++;
                sbb.Push(seg);
            }
        }
Exemplo n.º 2
0
        private unsafe void CaptureStateDelta(byte[] currentState)
        {
            // Keep in mind that everything captured here is intended to be played back in
            // reverse. The goal is, given the current state, how to get back to the previous
            // state. That's why the data portion of the delta comes from the previous state,
            // and also why the previous state is used if we have to bail out and capture the
            // full state instead.
            if (currentState.Length != _lastState.Length)
            {
                // If the state sizes mismatch, capture a full state rather than trying to do anything clever
                goto CaptureFullState;
            }

            if (currentState.Length == 0)
            {
                // handle empty states as a "full" (empty) state
                goto CaptureFullState;
            }

            int  index                         = 0;
            int  stateLength                   = Math.Min(currentState.Length, _lastState.Length);
            bool inChangeSequence              = false;
            int  changeSequenceStartOffset     = 0;
            int  lastChangeSequenceStartOffset = 0;

            if (_deltaBuffer.Length < stateLength + 1)
            {
                _deltaBuffer = new byte[stateLength + 1];
            }

            _deltaBuffer[index++] = 0;             // Full state = false (i.e. delta)

            fixed(byte *pCurrentState = &currentState[0])
            fixed(byte *pLastState = &_lastState[0])
            for (int i = 0; i < stateLength; i++)
            {
                bool thisByteMatches = *(pCurrentState + i) == *(pLastState + i);

                if (inChangeSequence == false)
                {
                    if (thisByteMatches)
                    {
                        continue;
                    }

                    inChangeSequence          = true;
                    changeSequenceStartOffset = i;
                }

                if (thisByteMatches || i == stateLength - 1)
                {
                    const int MaxHeaderSize = 10;
                    int       length        = i - changeSequenceStartOffset + (thisByteMatches ? 0 : 1);

                    if (index + length + MaxHeaderSize >= stateLength)
                    {
                        // If the delta ends up being larger than the full state, capture the full state instead
                        goto CaptureFullState;
                    }

                    // Offset Delta
                    VLInteger.WriteUnsigned((uint)(changeSequenceStartOffset - lastChangeSequenceStartOffset), _deltaBuffer, ref index);

                    // Length
                    VLInteger.WriteUnsigned((uint)length, _deltaBuffer, ref index);

                    // Data
                    Buffer.BlockCopy(_lastState, changeSequenceStartOffset, _deltaBuffer, index, length);
                    index += length;

                    inChangeSequence = false;
                    lastChangeSequenceStartOffset = changeSequenceStartOffset;
                }
            }

            _rewindBuffer.Push(new ArraySegment <byte>(_deltaBuffer, 0, index));

            UpdateLastState(currentState);
            return;

CaptureFullState:
            CaptureStateNonDelta(_lastState);
            UpdateLastState(currentState);
        }
Exemplo n.º 3
0
        private unsafe void CaptureRewindStateDelta(byte[] currentState)
        {
            // in case the state sizes mismatch, capture a full state rather than trying to do anything clever
            if (currentState.Length != _lastState.Length)
            {
                CaptureRewindStateNonDelta(_lastState);
                UpdateLastState(currentState);
                return;
            }

            int  index                         = 0;
            int  stateLength                   = Math.Min(currentState.Length, _lastState.Length);
            bool inChangeSequence              = false;
            int  changeSequenceStartOffset     = 0;
            int  lastChangeSequenceStartOffset = 0;

            if (_deltaBuffer.Length < stateLength)
            {
                _deltaBuffer = new byte[stateLength];
            }

            _deltaBuffer[index++] = 0;             // Full state = false (i.e. delta)

            fixed(byte *pCurrentState = &currentState[0])
            fixed(byte *pLastState = &_lastState[0])
            for (int i = 0; i < stateLength; i++)
            {
                bool thisByteMatches = *(pCurrentState + i) == *(pLastState + i);

                if (inChangeSequence == false)
                {
                    if (thisByteMatches)
                    {
                        continue;
                    }

                    inChangeSequence          = true;
                    changeSequenceStartOffset = i;
                }

                if (thisByteMatches || i == stateLength - 1)
                {
                    const int maxHeaderSize = 10;
                    int       length        = i - changeSequenceStartOffset + (thisByteMatches ? 0 : 1);

                    if (index + length + maxHeaderSize >= stateLength)
                    {
                        // If the delta ends up being larger than the full state, capture the full state instead
                        CaptureRewindStateNonDelta(_lastState);
                        UpdateLastState(currentState);
                        return;
                    }

                    // Offset Delta
                    VLInteger.WriteUnsigned((uint)(changeSequenceStartOffset - lastChangeSequenceStartOffset), _deltaBuffer, ref index);

                    // Length
                    VLInteger.WriteUnsigned((uint)length, _deltaBuffer, ref index);

                    // Data
                    Buffer.BlockCopy(_lastState, changeSequenceStartOffset, _deltaBuffer, index, length);
                    index += length;

                    inChangeSequence = false;
                    lastChangeSequenceStartOffset = changeSequenceStartOffset;
                }
            }

            _rewindBuffer.Push(new ArraySegment <byte>(_deltaBuffer, 0, index));

            UpdateLastState(currentState);
        }
Exemplo n.º 4
0
        private void CaptureRewindStateDelta(byte[] currentState, bool isSmall)
        {
            // in case the state sizes mismatch, capture a full state rather than trying to do anything clever
            if (currentState.Length != _lastState.Length)
            {
                CaptureRewindStateNonDelta(currentState);
                return;
            }

            var beginChangeSequence = -1;
            var inChangeSequence    = false;

            // try to set up the buffer in advance so we dont ever have exceptions in here
            // zeromus says: this sets off red flags for me. vecna got an exception that might be related to this inflating to 2x the input size. we should add an emergency check, or analyze how much it could inflate by (perhaps 3x would be adequate in every case?)
            if (_tempBuf.Length < currentState.Length)
            {
                _tempBuf = new byte[currentState.Length * 2];
            }

            var ms = new MemoryStream(_tempBuf, 0, _tempBuf.Length, true, true);

RETRY:
            try
            {
                var writer = new BinaryWriter(ms);
                writer.Write(false);                 // delta state
                for (int i = 0; i < currentState.Length; i++)
                {
                    if (inChangeSequence == false)
                    {
                        if (i >= _lastState.Length)
                        {
                            continue;
                        }

                        if (currentState[i] == _lastState[i])
                        {
                            continue;
                        }

                        inChangeSequence    = true;
                        beginChangeSequence = i;
                    }

                    if (i - beginChangeSequence == 254 || i == currentState.Length - 1)
                    {
                        writer.Write((byte)(i - beginChangeSequence + 1));
                        if (isSmall)
                        {
                            writer.Write((ushort)beginChangeSequence);
                        }
                        else
                        {
                            writer.Write(beginChangeSequence);
                        }

                        writer.Write(_lastState, beginChangeSequence, i - beginChangeSequence + 1);
                        inChangeSequence = false;
                        continue;
                    }

                    if (currentState[i] == _lastState[i])
                    {
                        writer.Write((byte)(i - beginChangeSequence));
                        if (isSmall)
                        {
                            writer.Write((ushort)beginChangeSequence);
                        }
                        else
                        {
                            writer.Write(beginChangeSequence);
                        }

                        writer.Write(_lastState, beginChangeSequence, i - beginChangeSequence);
                        inChangeSequence = false;
                    }
                }
            }
            catch (NotSupportedException)
            {
                // ok... we had an exception after all
                // if we did actually run out of room in the memorystream, then try it again with a bigger buffer
                _tempBuf = new byte[_tempBuf.Length * 2];
                goto RETRY;
            }

            if (_lastState != null && _lastState.Length == currentState.Length)
            {
                Buffer.BlockCopy(currentState, 0, _lastState, 0, _lastState.Length);
            }
            else
            {
                _lastState = (byte[])currentState.Clone();
            }

            var seg = new ArraySegment <byte>(_tempBuf, 0, (int)ms.Position);

            _rewindBuffer.Push(seg);
        }
Exemplo n.º 5
0
 private static void test(string[] args)
 {
     var sbb = new StreamBlobDatabase(false, 1024, test_BufferManage);
     Random r = new Random(0);
     byte[] temp = new byte[1024];
     int trials = 0;
     for (; ; )
     {
         int len = r.Next(1024) + 1;
         if (r.Next(100) == 0)
             len = 1024;
         ArraySegment<byte> seg = new ArraySegment<byte>(temp, 0, len);
         Console.WriteLine("{0} - {1}", trials, seg.Count);
         if (seg.Count == 1024)
             Console.Write("*************************");
         trials++;
         sbb.Push(seg);
     }
 }