/// <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(); }
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) + ";"); } } }