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