Ejemplo n.º 1
0
        /// <summary>
        /// Декодирование последовательности файлов
        /// </summary>
        private void Decode()
        {     
            // Список поврежденных основных томов
            int[] damagedVolList = new int[_dataCount];

            // Счетчик количества поврежденных томов
            int damagedVolCount = 0;

            // Создаем RAID-подобный декодер Рида-Соломона            
            if (_eRSRaidDecoder == null)
            {
                _eRSRaidDecoder = new RSRaidDecoder(_dataCount, _eccCount, _volList);

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

                        //...и сами засыпаем
                        ManualResetEvent.WaitAll(_executeEvent);

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

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

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

                        continue;
                    }

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

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

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

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

                        return;
                    }

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

                } // while(true)

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

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

                return;
            }

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

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

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

                // Открываем входные файловые потоки
                for (int i = 0; i < _dataCount; i++)
                {
                    // Считываем первоначальное имя файла,...
                    filename = _filename;

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

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

                    //...производим тест на наличие файла...                    
                    if (!File.Exists(filename))
                    {
                        // Указываем на то, что произошла ошибка работы с файлами
                        _processedOK = false;

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

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

                        return;
                    }

                    //...и открываем на его основе входной файловый поток
                    fileStreamSourceArr[i] = new BufferedStream(new FileStream(filename, FileMode.Open, System.IO.FileAccess.Read));
                }
                                                                                             
                // Определяем, какие из основных томов (по данным "_volList") повреждены,
                // а какие - нет
                for (int i = 0; i < _volList.Length; i++)
                {
                    // Вычисляем номер текущего тома
                    int currVol = Math.Abs(_volList[i]);

                    // Если данный том не является основным...
                    if (currVol >= _dataCount)
                    {
                        //...указываем, на данный факт
                        damagedVolList[damagedVolCount++] = i;
                    }
                }
                                                                
                // Открываем выходные файловые потоки для поврежденных файлов
                for (int i = 0; i < damagedVolCount; i++)
                {
                    // Считываем первоначальное имя файла,...
                    filename = _filename;

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

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

                    //...и открываем на его основе выходной файловый поток
                    fileStreamTargetArr[damagedVolList[i]] = 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 - 8) / 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));
                    }

                    // Декодируем данные (получаем полный корректный вектор основных томов)
                    _eRSRaidDecoder.Process(source, ref target);

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

                        // Теперь пишем пару байт в выходной поток
                        fileStreamTargetArr[damagedVolList[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 < damagedVolCount; i++)
                {
                    // Сначала пишем фиктивные 8 байт вместо реальной CRC-64,
                    // а, затем, закрываем файл.
                    if (fileStreamTargetArr[damagedVolList[i]] != null)
                    {
                        fileStreamTargetArr[damagedVolList[i]].Write(new byte[8], 0, 8);
                        fileStreamTargetArr[damagedVolList[i]].Flush();
                        fileStreamTargetArr[damagedVolList[i]].Close();
                        fileStreamTargetArr[damagedVolList[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 < damagedVolCount; i++)
                {
                    if (fileStreamTargetArr[damagedVolList[i]] != null)
                    {
                        fileStreamTargetArr[damagedVolList[i]].Flush();
                        fileStreamTargetArr[damagedVolList[i]].Close();
                        fileStreamTargetArr[damagedVolList[i]] = null;
                    }                    
                }

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

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

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

                return;
            }

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

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

            // Устанавливаем событие завершения обработки
            _finishedEvent[0].Set();
        }
Ejemplo n.º 2
0
        private static void Main(string[] args)
        {
            RSRaidDecoder eRSRaidDecoder = new RSRaidDecoder();
            Random eRandom = new Random();

            Console.Clear();
            Console.WriteLine("");
            Console.WriteLine("Recovery Star 2.22 (Cauchy Reed-Solomon Decoder Test)");
            Console.WriteLine("");

            // ��������� ����������� ���������� �����
            Console.Write("Enter MINIMUM count of volumes: ");
            int minVolCount = Convert.ToInt16(Console.ReadLine());

            // ��������� ������������ ���������� �����
            Console.Write("Enter MAXIMUM count of volumes: ");
            int maxVolCount = Convert.ToInt16(Console.ReadLine());
            Console.WriteLine("");

            // ���� ������������ ��������� �������� � ������� - ������ �� �������
            if(maxVolCount < minVolCount)
            {
                int temp = maxVolCount;
                maxVolCount = minVolCount;
                minVolCount = temp;
            }

            // ���������� �������� c ������ OK
            int OKCount = 0;

            // ���������� �������� c ������ Error
            int ErrorCount = 0;

            // ����� ���������� ��������
            int TotalCount = 0;

            while(true)
            {
                // ������������� ��������� ���������� �����
                int allVolCount = minVolCount + eRandom.Next((maxVolCount - minVolCount) + 1);

                // ���������� ����� ��� �������������� �� ��������� ���������� ����� ������
                int eccCount = 1 + eRandom.Next((allVolCount / 2) - 1);

                // ���������� ����� ������ ������� �� ����������� ��������
                int dataCount = allVolCount - eccCount;

                // ��������� ������ ����� (������ � ������������)
                ArrayList allVolList = new ArrayList(allVolCount);
                for(int i = 0; i < allVolCount; i++) allVolList.Add(i);

                // ����������� ��� ���� ��� �������������� ��� ��������� �����������
                // ��������� ����������� ����������
                int nErasures = eccCount;

                // ���������� ������ ���� ������!
                for(int i = 0; i < nErasures; i++) allVolList.RemoveAt(eRandom.Next(allVolList.Count - eccCount));

                // ��������� ������� ��� ��������...
                int[] volList = new int[dataCount];

                // �������� ������ ������ �������� ����� � ������ ��� ��������...
                for(int i = 0; i < dataCount; i++) volList[i] = (int)allVolList[i];

                // ������������� ������������ ��������...
                eRSRaidDecoder.SetConfig(dataCount, eccCount, volList, (int)RSType.Cauchy);

                // �������������� ����� �������� �������...
                if(!eRSRaidDecoder.Prepare(false))
                {
                    // ���������� � ���� ������ ��������� ������������
                    String logFileName = "Error " + DateTime.Now.ToString().Replace(':', '.') + ".txt";

                    File.AppendAllText(logFileName, "dataCount:" + Convert.ToString(dataCount + "; "), Encoding.ASCII);
                    File.AppendAllText(logFileName, "eccCount:" + Convert.ToString(eccCount + "; "), Encoding.ASCII);

                    for(int i = 0; i < dataCount; i++)
                    {
                        if(volList[i] < dataCount)
                        {
                            File.AppendAllText(logFileName, "d:" + Convert.ToString(volList[i] + "; "), Encoding.ASCII);
                        }
                        else
                        {
                            File.AppendAllText(logFileName, "e:" + Convert.ToString(volList[i] + "; "), Encoding.ASCII);
                        }
                    }

                    ErrorCount++;
                }

                TotalCount++;
                OKCount = TotalCount - ErrorCount;

                if((TotalCount % 100) == 0)
                {
                    Console.WriteLine("OK: " + Convert.ToString(OKCount) + ", " +
                                      "Errors: " + Convert.ToString(ErrorCount) + ";");
                }
            }
        }