static ExitStatus Run(BinaryReader sourceReader, BinaryWriter destinationWriter, IPackerEngine packer, PackerMode packerMode, int blockLength, int parallelismDegree, CancellationTokenSource token, ILoggable logger) { int blocksNumber = (int)Math.Ceiling((double)sourceReader.BaseStream.Length / blockLength); Stopwatch watcher = new Stopwatch(); watcher.Start(); logger?.LogMessage("Parallel Packer started:"); logger?.LogMessage($" {packerMode.ToString().ToLower()}ing..."); try { if (packerMode == PackerMode.Unpack) // we should save blockLength into the packed file because of blockLength parameter can be shanged { (blocksNumber, blockLength) = BinaryBlockReader.ReadBlockInfo(sourceReader); } var commonSourceConveyer = new LockableConveyer <Block>(); var commonDestinationConveyer = new LockableConveyer <Block>(); var workers = new List <IWorkable> { WorkerFactory.CreateSourceWorker(sourceReader, blocksNumber, blockLength, packerMode, commonSourceConveyer, logger), WorkerFactory.CreateDestinationWorker(destinationWriter, blocksNumber, blockLength, packerMode, commonDestinationConveyer, logger) }; for (int index = 1; index <= parallelismDegree; ++index) { workers.Add(WorkerFactory.CreatePackerWorker(index, packerMode, packer, commonSourceConveyer, commonDestinationConveyer, logger)); } WorkerFactory.DoWork(workers, token); watcher.Stop(); if (token.IsCancellationRequested) { logger?.LogMessage($"{packerMode}ing has been cancelled by user '{Environment.UserName}' after {watcher.Elapsed}"); return(ExitStatus.CANCEL); } else { logger?.LogMessage($"{packerMode}ing has been finished successfully in {watcher.Elapsed}:"); logger?.LogMessage($" total blocks number: {blocksNumber}"); logger?.LogMessage($" raw block length: {blockLength}"); return(ExitStatus.SUCCESS); } } catch (Exception e) { watcher.Stop(); logger?.LogError($"{packerMode}ing finished with ERRORS in {watcher.Elapsed}:", e); return(ExitStatus.ERROR); } }
public static Worker <Block, Block> CreateSourceWorker(BinaryReader reader, int blocksNumber, int blockLength, PackerMode packerMode, IPuttableConveyer <Block> puttableConveyer, ILoggable logger) { IEnumerator <Block> enumerator; if (packerMode == PackerMode.Pack) { enumerator = BinaryBlockReader.CreateRawBlocksEnumerator(reader, blockLength); } else { enumerator = BinaryBlockReader.CreatePackedBlocksEnumerator(reader, blocksNumber); } IGettableConveyer <Block> gettableConveyer = new GetOnlyConveyer <Block>((out bool stopped) => { stopped = !enumerator.MoveNext(); return(stopped ? null : enumerator.Current); }); return(new Worker <Block, Block>("Source", gettableConveyer, puttableConveyer, logger, block => block)); }