예제 #1
0
        /// <summary>
        /// Кодирование последовательности файлов
        /// </summary>
        private void Encode()
        {
            // Создаем RAID-подобный кодер Рида-Соломона
            if (_eRSRaidEncoder == null)
            {
                _eRSRaidEncoder = new RSRaidEncoder(_dataCount, _eccCount);

            } else
            {
                _eRSRaidEncoder.SetConfig(_dataCount, _eccCount);
            }

            // Подписываемся на делегатов
            _eRSRaidEncoder.OnUpdateRSMatrixFormingProgress = OnUpdateRSMatrixFormingProgress;
            _eRSRaidEncoder.OnRSMatrixFormingFinish = OnRSMatrixFormingFinish;

            // Запускаем подготовку RAID-подобного кодера Рида-Соломона
            if (_eRSRaidEncoder.Prepare(true))
            {
                // Цикл ожидания завершения подготовки кодера Рида-Соломона к работе
                while (true)
                {
                    // Если не обнаружили установленного события "_executeEvent",
                    // то пользователь хочет, чтобы мы поставили обработку на паузу -                       
                    if (!ManualResetEvent.WaitAll(_executeEvent, 0, false))
                    {
                        //...приостанавливаем работу контролируемого алгоритма...                      
                        _eRSRaidEncoder.Pause();

                        //...и сами засыпаем
                        ManualResetEvent.WaitAll(_executeEvent);
                        
                        // А когда проснулись, указываем, что обработка должна продолжаться                            
                        _eRSRaidEncoder.Continue();
                    }

                    // Ждем любое из перечисленных событий...
                    int eventIdx = ManualResetEvent.WaitAny(new ManualResetEvent[] { _wakeUpEvent[0], _exitEvent[0], _eRSRaidEncoder.FinishedEvent[0] });

                    //...если получили сигнал к тому, чтобы проснуться -
                    // переходим на новую итерацию, т.к. просыпаемся
                    // перед постановкой на паузу...
                    if (eventIdx == 0)
                    {
                        //...предварительно сбросив событие, заставившее нас проснуться
                        _wakeUpEvent[0].Reset();

                        continue;
                    }

                    //...если получили сигнал к выходу из обработки...
                    if (eventIdx == 1)
                    {
                        //...останавливаем контролируемый алгоритм
                        _eRSRaidEncoder.Stop();

                        // Указываем на то, что обработка была прервана
                        _processedOK = false;

                        // Активируем индикатор актуального состояния переменных-членов
                        _finished = true;

                        // Устанавливаем событие завершения обработки
                        _finishedEvent[0].Set();

                        return;
                    }

                    //...если получили сигнал о завершении обработки вложенным алгоритмом...
                    if (eventIdx == 2)
                    {
                        //...выходим из цикла ожидания завершения (этого и ждали в while(true)!)
                        break;
                    }

                } // while(true)

            } else
            {
                // Сбрасываем флаг корректности результата
                _processedOK = false;

                // Активируем индикатор актуального состояния переменных-членов
                _finished = true;

                // Устанавливаем событие завершения обработки
                _finishedEvent[0].Set();

                return;
            }

            // Когда поток уже не работает, установленное им булевское свойство,
            // возможно, ещё "не проявилось". Достаточно необычная ситуация,
            // но факт - вещь упрямая.
            for (int i = 0; i < 9000; i++)
            {
                if (!_eRSRaidEncoder.Finished)
                {
                    Thread.Sleep(100);
                }
            }

            // Если кодер не сконфигурировался корректно - выходим...
            if (!_eRSRaidEncoder.ConfigIsOK)
            {
                //...указывая на ошибку
                _processedOK = false;

                // Активируем индикатор актуального состояния переменных-членов
                _finished = true;

                // Устанавливаем событие завершения обработки
                _finishedEvent[0].Set();

                return;
            }

            // Выделяем память под массивы входных и выходных данных кодера
            int[] source = new int[_dataCount];
            int[] target = new int[_eccCount];

            // "Маленький" буфер для работы с парами байт
            byte[] smallBuff = new byte[2];

            // Выделяем память под массивы файловых потоков
            BufferedStream[] fileStreamSourceArr = new BufferedStream[_dataCount];
            BufferedStream[] fileStreamTargetArr = new BufferedStream[_eccCount];
                       
            try
            {               
                // Имя файла для обработки
                String filename;

                // Номер текущего тома
                int volNum;

                // Инициализируем массивы файловых потоков основных томов
                for (volNum = 0; volNum < _dataCount; volNum++)
                {
                    // Считываем первоначальное имя файла,...
                    filename = _filename;

                    //...упаковываем его в префиксный формат...
                    _eFileNamer.Pack(ref filename, volNum, _dataCount, _eccCount);

                    //...формируем полное имя файла...
                    filename = _path + filename;

                    //...и открываем на его основе входной файловый поток
                    fileStreamSourceArr[volNum] = new BufferedStream(new FileStream(filename, FileMode.Open, System.IO.FileAccess.Read));
                }

                // Инициализируем массивы файловых потоков томов для восстановления
                for (int eccNum = 0; volNum < (_dataCount + _eccCount); volNum++, eccNum++)
                {
                    // Считываем первоначальное имя файла...
                    filename = _filename;

                    //...упаковываем его в префиксный формат...
                    _eFileNamer.Pack(ref filename, volNum, _dataCount, _eccCount);

                    //...формируем полное имя файла...
                    filename = _path + filename;

                    //...и открываем на его основе выходной файловый поток
                    fileStreamTargetArr[eccNum] = new BufferedStream(new FileStream(filename, FileMode.Create, System.IO.FileAccess.Write));                   
                }

                // Вычисляем значение модуля, который позволит выводить процент обработки
                // ровно при единичном приращении
                int progressMod1 = (int)(fileStreamSourceArr[0].Length / 200);

                // Если модуль равен нулю, то увеличиваем его до значения "1", чтобы
                // прогресс выводился на каждой итерации (файл очень маленький)
                if (progressMod1 == 0)
                {
                    progressMod1 = 1;
                }
                                                                   
                // Работаем со всеми срезами пар байт в исходных потоках
                for (int i = 0; i < (fileStreamSourceArr[0].Length / 2); i++)
                {
                    // Заполняем вектор исходных данных кодера данными текущего среза
                    for (int j = 0; j < _dataCount; j++)
                    {
                        // Читаем пару байт из входного потока
                        fileStreamSourceArr[j].Read(smallBuff, 0, 2);

                        // Производим слияние двух значений byte в int
                        source[j] = (int)(((uint)(smallBuff[0] << 0) & 0x00FF)
                                           |
                                          ((uint)(smallBuff[1] << 8) & 0xFF00));
                    }

                    // Кодируем данные (получаем тома для восстановления)
                    _eRSRaidEncoder.Process(source, ref target);

                    // Выводим в файлы вектор избыточных данных (ecc)
                    for (int j = 0; j < _eccCount; j++)
                    {            
                        // Производим разделение одного значения на два (int16 на два byte)
                        smallBuff[0] = (byte)((target[j] >> 0) & 0x00FF);
                        smallBuff[1] = (byte)((target[j] >> 8) & 0x00FF);

                        // Теперь пишем пару байт в выходной поток
                        fileStreamTargetArr[j].Write(smallBuff, 0, 2);
                    }

                    // Выводим прогресс обработки через каждый процент
                    if (
                            ((i % progressMod1) == 0)
                         &&
                            (OnUpdateFileCodingProgress != null)
                       )
                    {
                        OnUpdateFileCodingProgress(((double)(i + 1) / (double)fileStreamSourceArr[0].Length) * 200.0);
                    }

                    // В случае, если требуется постановка на паузу, событие "_executeEvent"
                    // будет сброшено, и будем на паузе вплоть до его появления
                    ManualResetEvent.WaitAll(_executeEvent);

                    // Если указано, что требуется выйти из потока - выходим
                    if (ManualResetEvent.WaitAll(_exitEvent, 0, false))
                    {
                        // Закрываем входные файловые потоки
                        for (int j = 0; j < _dataCount; j++)
                        {
                            if (fileStreamSourceArr[j] != null)
                            {
                                fileStreamSourceArr[j].Close();
                                fileStreamSourceArr[j] = null;
                            }
                        }

                        // Закрываем выходные файловые потоки
                        for (int j = 0; j < _eccCount; j++)
                        {
                            if (fileStreamTargetArr[j] != null)
                            {
                                fileStreamTargetArr[j].Close();
                                fileStreamTargetArr[j] = null;
                            }
                        }

                        // Указываем на то, что обработка была прервана
                        _processedOK = false;

                        // Активируем индикатор актуального состояния переменных-членов
                        _finished = true;

                        // Устанавливаем событие завершения обработки
                        _finishedEvent[0].Set();

                        return;
                    }
                }
                
                // Закрываем входные файловые потоки
                for (int i = 0; i < _dataCount; i++)
                {
                    if (fileStreamSourceArr[i] != null)
                    {
                        fileStreamSourceArr[i].Close();
                        fileStreamSourceArr[i] = null;
                    }
                }

                // Закрываем выходные файловые потоки
                for (int i = 0; i < _eccCount; i++)
                {
                    if (fileStreamTargetArr[i] != null)
                    {
                        fileStreamTargetArr[i].Flush();
                        fileStreamTargetArr[i].Close();
                        fileStreamTargetArr[i] = null;
                    }
                }

                // Сообщаем, что обработка файлов закончена
                if (OnFileCodingFinish != null)
                {
                    OnFileCodingFinish();
                }
            }

            // Если было хотя бы одно исключение - закрываем файловый поток и
            // сообщаем об ошибке
            catch (IOException e)
            {
                // Закрываем входные файловые потоки
                for (int i = 0; i < _dataCount; i++)
                {
                    if (fileStreamSourceArr[i] != null)
                    {
                        fileStreamSourceArr[i].Close();
                        fileStreamSourceArr[i] = null;
                    }
                }

                // Закрываем выходные файловые потоки
                for (int i = 0; i < _eccCount; i++)
                {
                    if (fileStreamTargetArr[i] != null)
                    {
                        fileStreamTargetArr[i].Close();
                        fileStreamTargetArr[i] = null;
                    }
                }

                // Указываем на то, что произошла ошибка работы с файлами
                _processedOK = false;

                // Активируем индикатор актуального состояния переменных-членов
                _finished = true;

                // Устанавливаем событие завершения обработки
                _finishedEvent[0].Set();

                return;
            }           

            // Указываем на то, что обработка была произведена корректно
            _processedOK = true;

            // Активируем индикатор актуального состояния переменных-членов
            _finished = true;

            // Устанавливаем событие завершения обработки
            _finishedEvent[0].Set();
        }
예제 #2
0
        /// <summary>
        /// ���� �� �������������� (����� ����-��������)
        /// </summary>
        private void Benchmark()
        {
            // ������� RAID-�������� ����� ����-��������
            if(this.eRSRaidEncoder == null)
            {
                this.eRSRaidEncoder = new RSRaidEncoder(this.dataCount, this.eccCount, this.codecType);
            }

            // ������������� �� ���������
            this.eRSRaidEncoder.OnUpdateRSMatrixFormingProgress = new OnUpdateDoubleValueHandler(OnUpdateRSMatrixFormingProgress);
            this.eRSRaidEncoder.OnRSMatrixFormingFinish = new OnEventHandler(OnRSMatrixFormingFinish);

            // ��������� ���������� RAID-��������� ������ ����-��������
            if(this.eRSRaidEncoder.Prepare(true))
            {
                // ���� �������� ���������� ���������� ������ ����-�������� � ������
                while(true)
                {
                    // ���� ����� �� ������������� �������...
                    int eventIdx = ManualResetEvent.WaitAny(new ManualResetEvent[] {this.exitEvent[0], this.eRSRaidEncoder.FinishedEvent[0]});

                    //...���� �������� ������ � ������ �� ���������...
                    if(eventIdx == 0)
                    {
                        //...������������� �������������� ��������
                        this.eRSRaidEncoder.Stop();

                        return;
                    }

                    //...���� �������� ������ � ���������� ��������� ��������� ����������...
                    if(eventIdx == 1)
                    {
                        //...������� �� ����� �������� ���������� (����� � ����� � while(true)!)
                        break;
                    }
                } // while(true)
            }

            // ����� ����� ��� �� ��������, ������������� �� ��������� ��������,
            // ��������, ��� "�� ����������"
            for(int i = 0; i < (int)WaitCount.MaxWaitCount; i++)
            {
                if(!this.eRSRaidEncoder.Finished)
                {
                    Thread.Sleep((int)WaitTime.MinWaitTime);
                }
                else
                {
                    break;
                }
            }

            // ���� ����� �� ����������������� ��������� - �������...
            if(!this.eRSRaidEncoder.ConfigIsOK)
            {
                string message = "Reed-Solomon Coder configuration error!";
                string caption = " Recovery Star 2.22";
                MessageBoxButtons buttons = MessageBoxButtons.OK;
                MessageBox.Show(null, message, caption, buttons, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);

                return;
            }

            // �������� ������ ��� ������� ������� � �������� ������ ������
            int[] sourceLog = new int[this.dataCount];
            int[] target = new int[this.eccCount];

            // ����� ��� ������ � ������ ����
            byte[] wordBuff = new byte[2];

            // ������ ��� �������� ����������� �������� �������
            byte[] fileStreamImitator_0 = new byte[this.dataCount];
            byte[] fileStreamImitator_1 = new byte[this.dataCount];

            // �������������� ��������� ��������� �����
            Random eRandom = new Random((int)System.DateTime.Now.Ticks);

            // ��������� ������ ���������� �������
            eRandom.NextBytes(fileStreamImitator_0);
            eRandom.NextBytes(fileStreamImitator_1);

            // ��������� �������� ������� �� ������������ ������ �������
            long DateTimeTicksNow = -1;

            // ���������� ������� ���������� ������������ ����
            this.processedBytesCount = 0;

            // ��������� ��������� �������� ������� �� ������ ������� �����
            this.DateTimeTicksOnStart = System.DateTime.Now.Ticks;

            // ����������� ���� ������������ ������ ����-��������
            while(true)
            {
                // ��������� ������ �������� ������ ������ ������� �������� �����
                for(int j = 0; j < this.dataCount; j++)
                {
                    // ������ ���� ���� �� �������� ������
                    wordBuff[0] = fileStreamImitator_0[j];
                    wordBuff[1] = fileStreamImitator_1[j];

                    // ���������� ������� ���� �������� byte � int
                    sourceLog[j] = this.eGF16.Log((int)(((uint)(wordBuff[0] << 0) & 0x00FF)
                                                        |
                                                        ((uint)(wordBuff[1] << 8) & 0xFF00)));
                }

                // �������� ������ (�������� ���� ��� ��������������)
                this.eRSRaidEncoder.Process(sourceLog, target);

                // ������� � ����� ������ ���������� ������ (ecc)
                for(int j = 0; j < this.eccCount; j++)
                {
                    // ���������� ���������� ������ �������� �� ��� (int16 �� ��� byte)
                    wordBuff[0] = (byte)((target[j] >> 0) & 0x00FF);
                    wordBuff[1] = (byte)((target[j] >> 8) & 0x00FF);

                    // ������ ����� ���� ���� � �������� �����...
                    // �.�. ��� ���� - �������� ������ ������ �� ���� �� ������������
                }

                // ��������� �������� �������
                DateTimeTicksNow = System.DateTime.Now.Ticks;

                // ������������� ���������� ������������ ����
                this.processedBytesCount += (2 * this.dataCount);

                // ������� ����������� ���� � ����������� �������...
                if(this.coderStatSema.WaitOne(0, false))
                {
                    // ��������� ����� ������ ����� � �������� (1 ��� == 10^-07 �������)
                    // 0x01 - ����� �� �������� ������� �� ����
                    this.timeInTest = ((double)((DateTimeTicksNow - this.DateTimeTicksOnStart) | 0x01) / 10000000.0);

                    // ��������� ������������ ����� ������ � ����������
                    this.processedDataCount = ((double)this.processedBytesCount / (double)(1024 * 1024));

                    // ���������� ��������� "V" �� ��������...
                    this.coderStatSema.Release();
                }

                // � ������, ���� ��������� ���������� �� �����, ������� "executeEvent"
                // ����� ��������, � ����� �� ����� ������ �� ��� ���������
                ManualResetEvent.WaitAll(this.executeEvent);

                // ���� �������� ������ � ������ �� ���������...
                if(ManualResetEvent.WaitAll(this.exitEvent, 0, false))
                {
                    return;
                }
            } // while(true)
        }