/// <summary>
        /// Метод для потока чтения. Чтение и генерация задач сжатия происходит в 1 поток, что даёт максимальную нагрузку на диск
        /// </summary>
        /// <param name="obj">
        /// Дескриптор файла для чтения
        /// </param>
        private void ReadingThread(object obj)
        {
            FileDescriptor readFile = obj as FileDescriptor;

            _fileLength = readFile.GetDescription.Length;
            try
            {
                using (FileStream fileToBeDecompressed = readFile.GetDescription.OpenRead())
                {
                    // Читать блоки архива, пока не закончится файл
                    while (fileToBeDecompressed.Position < _fileLength && !_cancellationToken.IsCancellationRequested)
                    {
                        _position = fileToBeDecompressed.Position;
                        // Защита от переполнения памяти
                        if (_compressTaskPool.TaskCount() > _maxTasks * _cores)
                        {
                            Thread.Sleep(_sleep);
                            continue;
                        }
                        ITaskInfo task = _taskFactory.CreateReadTaskInfo(_batchCount, 0);
                        _compressTaskPool.AddTask(_taskFactory.CreateProcessTaskInfo(_batchCount++, task.Execute(fileToBeDecompressed) as byte[]));
                    }
                    _isReading = false;
#if DEBUG
                    Console.WriteLine("End of reading");
#endif
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine("Error on file reading");
#if DEBUG
                Console.WriteLine(exc);
#endif
            }
        }
Beispiel #2
0
        /// <summary>
        /// Запустить сжатие заданного файла и сохранить по указанному пути
        /// </summary>
        /// <param name="readFile">
        /// Дескриптор файла для чтения
        /// </param>
        /// <param name="writeFile">
        /// Дескриптор файла для записи
        /// </param>
        public bool ProcessFile(FileDescriptor readFile, FileDescriptor writeFile)
        {
            _readTaskPool     = new QueueTaskPool();
            _compressTaskPool = new QueueTaskPool();
            _writeTaskPool    = new HashtableTaskPool();

            /// Длина исходного файла
            Int64 _fileLength = readFile.GetDescription.Length;

            // Количество целых кусков
            _batchCount = _fileLength / _readBlockSize;
            // Длина последнего куска
            _lastPiece = _fileLength % _readBlockSize;
            // Общее количество кусков с учётом последнего
            _totalCount = _batchCount;

            if (_lastPiece > 0)
            {
                _totalCount++;
            }

            try
            {
                // Запуск потока чтения
                Thread readingThread = new Thread(ReadingThread);
                readingThread.Start(readFile);

                // Запустить потоки распаковки
                for (int i = 0; i < _cores; ++i)
                {
                    Thread compressingThread = new Thread(CompressingThread);
                    compressingThread.Start();
                }

                // Запустить поток записи
                Thread writingThread = new Thread(WritingThread);
                writingThread.Start(writeFile);

                // Запуск потока генерации задач
                Thread generatorThread = new Thread(GeneratorThread);
                generatorThread.Start();

                // Наблюдатель - ждёт, пока не завершится последний кусок и обновляет прогресс
                while (_lastWritedBlock < _totalCount && !_cancellationToken.IsCancellationRequested)
                {
#if !DEBUG
                    Console.Clear();
#endif
                    Console.WriteLine("Press Ctrl+C for cancellation");
                    // Здесь должно высылаться оповещение контроллеру, чтобы тот обновил на GUI прогресс бар (W.I.P.) =]
                    Console.WriteLine("Progress: {0}%", Math.Truncate(_lastWritedBlock / (double)_totalCount * 100));
                    Thread.Sleep(500);
                }

                if (_cancellationToken.IsCancellationRequested)
                {
                    Console.WriteLine("Compression cancelled");
                    return(false);
                }

#if !DEBUG
                Console.Clear();
#endif
                Console.WriteLine("Compression completed");
                return(true);
            }
            catch (Exception exc)
            {
                Console.WriteLine("Can't process threads");
#if DEBUG
                Console.WriteLine(exc);
#endif
                return(false);
            }
        }
        public static void Decompress(string open_path, string save_path)
        {
            try
            {
                // Токен для отмены процесса
                CancellationTokenSource cancellationToken = new CancellationTokenSource();
                Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs args)
                {
                    args.Cancel = true;
                    cancellationToken.Cancel();
                };

                // Контейнеры для описаний файлов
                FileDescriptor open = new FileDescriptor(open_path);
                FileDescriptor save = new FileDescriptor(save_path + open.GetDescription.Name.Replace(".gz", ""));

                if (!File.Exists(open_path))
                {
                    Console.WriteLine("Source file is not exist");
                    throw new Exception();
                }
                if (!Directory.Exists(save_path))
                {
                    Console.WriteLine("Dir is not exist");
                    throw new Exception();
                }
                if (save.GetDescription.DirectoryName == ".gz")
                {
                    Console.WriteLine("Destination file extension is GZip");
                    throw new Exception();
                }
                if (open.GetDescription.Extension != ".gz")
                {
                    Console.WriteLine("Source file extension is not GZip");
                    throw new Exception();
                }

                DecompressorTaskFactory factory    = new DecompressorTaskFactory();
                Decompressor            progamMode = new Decompressor(cancellationToken.Token, factory, Environment.ProcessorCount, Environment.ProcessorCount);

#if DEBUG
                var timer = new Stopwatch();
                timer.Start();
#endif
                // Запуск распаковки
                bool result = progamMode.ProcessFile(open, save);
                cancellationToken.Dispose();
#if DEBUG
                timer.Stop();
                Console.WriteLine(timer.Elapsed.TotalSeconds);
                Console.ReadKey();
#endif

                // Если процесс отменён, то удалить получившийся файл
                if (!result)
                {
                    if (File.Exists(save.GetDescription.FullName))
                    {
                        File.Delete(save.GetDescription.FullName);
                    }
                }
            }
            catch (Exception exc)
            {
#if DEBUG
                Console.WriteLine(exc);
#endif
                Console.ReadKey();
            }
        }
        public static void Compress(string open_path, string save_path)
        {
            try
            {
                // Токен для отмены процесса
                CancellationTokenSource cancellationToken = new CancellationTokenSource();
                Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs args)
                {
                    args.Cancel = true;
                    cancellationToken.Cancel();
                };

                // Контейнеры для описаний файлов
                FileDescriptor open = new FileDescriptor(open_path);
                FileDescriptor save = new FileDescriptor(save_path + open.GetDescription.Name + ".gz");

                // Обработка исключений
                if (!File.Exists(open_path))
                {
                    Console.WriteLine("Source file is not exist");
                    throw new Exception();
                }
                if (open.GetDescription.Extension == ".gz")
                {
                    Console.WriteLine("Source file extension is GZip");
                    throw new Exception();
                }
                if (!Directory.Exists(save_path))
                {
                    Console.WriteLine("Dir is not exist");
                    throw new Exception();
                }

                CompressionTaskFactory factory    = new CompressionTaskFactory();
                Compressor             progamMode = new Compressor(cancellationToken.Token, factory, 56636, Environment.ProcessorCount, Environment.ProcessorCount);

#if DEBUG
                // Замерить время сжатия
                var timer = new Stopwatch();
                timer.Start();
#endif
                // Запуск сжатия
                bool result = progamMode.ProcessFile(open, save);
                cancellationToken.Dispose();
#if DEBUG
                timer.Stop();
                Console.WriteLine(timer.Elapsed.TotalSeconds);
                Console.ReadKey();
#endif

                // Если процесс отменён, то удалить архив
                if (!result)
                {
                    if (File.Exists(save.GetDescription.FullName))
                    {
                        File.Delete(save.GetDescription.FullName);
                    }
                }
                else
                {
                    // Вывести уровень сжатия
                    Console.WriteLine("Compression level: " + Math.Truncate(save.GetDescription.Length / (double)open.GetDescription.Length * 100) + "%");
                }
            }
            catch (Exception exc)
            {
#if DEBUG
                Console.WriteLine(exc);
                Console.ReadKey();
#endif
            }
        }