Beispiel #1
0
		private static void ExecuteBlockConsumers(FileEnvironment e, out Dictionary<string, IBlockConsumer> blockConsumers, Stream altStream = null) {
			using(new ActivityTraceContext(ts, "ExecuteBlockConsumers")) {
				Stream fileStream;
				try {
					fileStream = altStream != null ? altStream : File.Open(e.File.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
					ts.TraceInformation("Successfully opened file");
				} catch(Exception ex) {
					ts.TraceData(TraceEventType.Error, 0, "Couldn't open file", ex);
					Console.WriteLine(ex.Message + "\n");
					blockConsumers = null;
					return;
				}

				using(fileStream) {
					Boolean isMatroska = MatroskaParser.IsMatroskaFile(fileStream);
					Boolean isOgmOgg = OgmOggParser.IsOgmOggFile(fileStream);

					BlockConsumerContainer.Progress progress = null;
					if((switches & eSwitches.UseAllHashes) != 0 || isMatroska || isOgmOgg) {
						ts.TraceInformation("Adding Blockconsumers");
#if(UseAICHHash)
						if((switches & (eSwitches.Aich)) != 0) hashContainer.AddHashAlgorithm("AICH");
#endif
						if((switches & (eSwitches.Crc)) != 0) e.Container.AddBlockConsumer("CRC");
						if((switches & (eSwitches.Ed2k)) != 0) e.Container.AddBlockConsumer("ED2K");
						if((switches & (eSwitches.Md4)) != 0) e.Container.AddBlockConsumer("MD4");
						if((switches & (eSwitches.Md5)) != 0) e.Container.AddBlockConsumer("MD5");
						if((switches & (eSwitches.Sha1)) != 0) e.Container.AddBlockConsumer("SHA1");
						if((switches & (eSwitches.Tiger)) != 0) e.Container.AddBlockConsumer("TIGER");
						if((switches & (eSwitches.Tth)) != 0) e.Container.AddBlockConsumer("TTH");
						//if((switches & (eSwitches.Tth)) != 0) e.Container.AddBlockConsumer("TTH2");
						//if((switches & (eSwitches.Tth)) != 0) e.Container.AddBlockConsumer("TTH3");
						if(isMatroska) e.Container.AddBlockConsumer("Matroska");
						if(isOgmOgg) e.Container.AddBlockConsumer("Ogm/Ogg");

						ts.TraceInformation("Consume file");
						progress = e.Container.Start(fileStream);
					}

					if((switches & eSwitches.SupressProgress) == 0) {
						try {
							DisplayBuffer(e, progress);

							//throw new Exception("Just me testing again");

						} catch(Exception ex) {
							Console.WriteLine();


							CursorVisible = true;


							e.AddException("Error in DisplayBuffer", ex);
						}
					}

					try {
						blockConsumers = e.Container.Join().ToDictionary(b => b.Name);
					} catch(Exception ex) {
						e.AddException("Error while waiting for BlockConsumers", ex);
						blockConsumers = null;
					}
				}
			}
		}
Beispiel #2
0
		private static void WriteLogs(FileEnvironment e, Dictionary<string, IBlockConsumer> blockConsumers) {
			using(new ActivityTraceContext(ts, "ExecuteBlockConsumers")) {
				bool acreqFile;
				var p = CreateInfoProvider(e, blockConsumers, out acreqFile);

				var detExt = p[StreamType.General, 0, EntryKey.Extension] != null ? p[StreamType.General, 0, EntryKey.Extension].Value.ToLower() : null;
				var ext = e.File.Extension.Length <= 1 ? "" : e.File.Extension.Substring(1).ToLower();

				if(!string.IsNullOrEmpty(extFixPath) && !string.IsNullOrEmpty(detExt) && !ext.Equals(detExt)) {
					ts.TraceInformation("Logging: Extension Fix");
					try {
						if(!detExt.Contains(' ')) {
							e.File.MoveTo(Path.ChangeExtension(e.File.FullName, detExt));
							AppendAllText(extFixPath, ext + " => " + detExt + "	" + e.File.FullName + Environment.NewLine, "Couldn't update extension fix file");
							ext = detExt;
						} else {
							AppendAllText(extFixPath, "FAILED: " + ext + " => " + detExt + "	" + e.File.FullName + Environment.NewLine, "Couldn't update extension fix file");
						}
					} catch(Exception ex) {
						AppendAllText(extFixPath, "FAILED: " + ext + " => " + detExt + "	" + e.File.FullName + Environment.NewLine, "Couldn't update extension fix file");
					}
				}

				#region Generate/Write Logs
				string log = "";
				try {
					if((switches & (eSwitches.CreqXmlFormat | eSwitches.NewCreqXmlFormat | eSwitches.MediaInfoXMLOutPut | eSwitches.MediaInfoOutPut)) != 0) {
						log = e.File.FullName + Environment.NewLine;
					}

					if((switches & eSwitches.CreqXmlFormat) != 0) {
						ts.TraceInformation("Logging: CreqXmlFormat");
						var tw = new StringWriter();
						Info.CreateAVDumpLog(p).Save(new SafeXmlWriter(tw, lowerCaseElements: true));
						log += tw.ToString();
					}
					if((switches & eSwitches.NewCreqXmlFormat) != 0) {
						ts.TraceInformation("Logging: NewCreqXmlFormat");
						var tw = new StringWriter();
						Info.CreateNewAVDumpLog(p).Save(new SafeXmlWriter(tw));
						log += tw.ToString();
					}
					if((switches & eSwitches.MediaInfoXMLOutPut) != 0) {
						ts.TraceInformation("Logging: MediaInfoXMLOutPut");
						var tw = new StringWriter();
						Info.CreateMediaInfoXMLLog(e.File.FullName, blockConsumers.Values).Save(new SafeXmlWriter(tw));
						log += tw.ToString();
					}
					if((switches & eSwitches.MediaInfoOutPut) != 0) {
						ts.TraceInformation("Logging: MediaInfoOutPut");
						log += Info.CreateMediaInfoDump(e.File.FullName);
					}
					if((switches & eSwitches.TxtFormat) != 0) {
						ts.TraceInformation("Logging: TxtFormat");
						log += Info.CreateTxtLog(e.File.FullName, p);
					}
					if((switches & eSwitches.HashOutput) != 0) {
						ts.TraceInformation("Logging: HashOutput");
						log += Info.CreateHashLog(e.File.FullName, p);
					}

					if(logPath != null && !String.IsNullOrEmpty(log)) AppendAllText(logPath, log + Environment.NewLine + Environment.NewLine, "Couldn't update logfile");
				} catch(FatalException ex) {
					throw;
				} catch(Exception ex) {
					e.AddException("Error while generating info report", ex);
				}
				#endregion

				if(!string.IsNullOrEmpty(log)) Console.WriteLine(log);
				Console.WriteLine();

#if(HasACreq)
				if(acreqFile && (dumpableExtensions.Contains(ext) || dumpableExtensions.Contains(detExt) || (switches & eSwitches.DumpAllExtensions) != 0) && !(string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))) {
					MemoryStream stream = new MemoryStream();

					byte[] creqBytes;
					using(var writer = new SafeXmlWriter(stream, new UTF8Encoding(), Formatting.None, lowerCaseElements: true)) {
						var xmlDoc = Info.CreateAVDumpLog(p);
						if(xmlDoc["file"]["md4"] != null) xmlDoc["file"].RemoveChild(xmlDoc["file"]["md4"]);
						if(xmlDoc["file"]["tiger"] != null) xmlDoc["file"].RemoveChild(xmlDoc["file"]["tiger"]);


						xmlDoc.Save(writer);

						creqBytes = new byte[stream.Length - 38];
						stream.Position = 38;
						stream.Read(creqBytes, 0, (int)stream.Length - 38);
					}
					anidb.QueryACReq(new ACReq(host, timeout * 1000, "avdumplib", appVersion.Build, username.ToLower(), password, creqBytes), new AniDB.QueryTag(e));
				}
#endif

				if(!string.IsNullOrEmpty(extDiffListPath) && !ext.Equals(detExt)) {
					AppendAllText(extDiffListPath, ext + " => " + (detExt == null ? "unknown" : detExt) + "	" + e.File.FullName + Environment.NewLine, "Couldn't update extension diff file");
				}

				#region DoneLog Stream Writing
				if(doneListPath != null && (username == null || password == null) && e.Exceptions.Count == 0) {
					ts.TraceInformation("Logging: DoneLog");
					AppendAllText(doneListPath, e.File.FullName + Environment.NewLine, "Couldn't update donelist file");
					int index = doneListContent.BinarySearch(e.File.FullName);
					if(index < 0) doneListContent.Insert(~index, e.File.FullName);
				}
				#endregion

				#region Ed2kLog Stream Writing
				Ed2k ed2k = null;
				if(blockConsumers.ContainsKey("ED2K")) ed2k = (Ed2k)((HashCalculator)blockConsumers["ED2K"]).HashObj;
				if(ed2k != null) {
					byte[] blueEd2kHash = ed2k.BlueHash; //Handle Ed2k screwup
					byte[] redEd2kHash = ed2k.Hash;

					if(ed2kListPath != null) {
						ts.TraceInformation("Logging: Ed2kLog");
						string ed2kStr = "ed2k://|file|" + e.File.Name + "|" + e.File.Length + "|" + BaseConverter.ToString(ed2k.Hash) + "|/";
						if(!ed2k.BlueIsRed) {
							ed2kStr += "*" + "ed2k://|file|" + e.File.Name + "|" + e.File.Length + "|" + BaseConverter.ToString(ed2k.BlueHash) + "|/";
						}
						AppendAllText(ed2kListPath, ed2kStr + Environment.NewLine, "Couldn't update ed2k list file");
					}
				}
				#endregion

				#region CRC Mismatch
				if(crcMismatchListPath != null && blockConsumers.ContainsKey("CRC")) {
					ts.TraceInformation("Logging: CRC Mismatch");
					string crcHash = BaseConverter.ToString(((HashCalculator)blockConsumers["CRC"]).HashObj.Hash);
					if(!e.File.Name.ToLower().Contains(crcHash.ToLower())) {
						AppendAllText(crcMismatchListPath, crcHash + " " + e.File.FullName + Environment.NewLine, "Couldn't update crcerr list file");

						ColoredWriteLine(ConsoleColor.Yellow, "Filename doesn't contain the calculated CRC (" + crcHash + ")");
					}
				}

				#endregion


				#region HashLog Stream Writing
				if(hashListPath != null) {
					ts.TraceInformation("Logging: HashLog");
					string formattedStr = hashLogStyle;
					foreach(HashCalculator hashExecute in blockConsumers.Values.Where(blockConsumer => { return blockConsumer is HashCalculator; })) {
						//if(hashExecute.HashObj is Ed2k) {
						//    string ed2kStr = "ed2k://|file|" + e.File.Name + "|" + e.File.Length + "|" + BaseConverter.ToString(hashExecute.HashObj.Hash) + "|/";
						//    if(!((Ed2k)hashExecute.HashObj).BlueIsRed) {
						//        ed2kStr += "*" + "ed2k://|file|" + e.File.Name + "|" + e.File.Length + "|" + BaseConverter.ToString(((Ed2k)hashExecute.HashObj).BlueHash) + "|/";
						//    }

						//    formattedStr = formattedStr.Replace("$" + hashExecute.Name + "$", ed2kStr);
						//} else {
						formattedStr = formattedStr.Replace("$" + hashExecute.Name + "$", BaseConverter.ToString(hashExecute.HashObj.Hash));
						//}
					}
					AppendAllText(hashListPath, formattedStr + Environment.NewLine, "Couldn't update hashlist file");
				}
				#endregion
			}
		}
Beispiel #3
0
		private static void ProcessMediaFile(FileEnvironment e) {
			using(new ActivityTraceContext(ts, "ProcessMediaFile")) {
				ts.TraceData(TraceEventType.Information, 0, e.File.FullName);
				Console.WriteLine("Folder: " + e.File.DirectoryName);
				Console.WriteLine("Filename: " + e.File.Name);

				if(e.File.Length == 0) {
					ts.TraceInformation("Skipping 0byte File");
					ColoredWriteLine(ConsoleColor.Red, "Skipping 0byte File", true);
					return;
				}

				ts.TraceInformation("Starting file processing");
				var startTime = DateTime.Now;
				Dictionary<string, IBlockConsumer> blockConsumers;
				ExecuteBlockConsumers(e, out blockConsumers);
				if(blockConsumers == null) {
					ts.TraceEvent(TraceEventType.Warning, 0, "blockConsumers is NULL, skipping file");
					return;
				}

				if((switches & eSwitches.PrintElapsedHashingTime) != 0) Console.WriteLine("Time elapsed after Hashing: " + (DateTime.Now - startTime).TotalSeconds + "s");

				foreach(var blockConsumer in blockConsumers.Values) {
					if(blockConsumer.Error != null) {
						ts.TraceData(TraceEventType.Error, 0, "BlockConsumer (" + blockConsumer.Name + ") threw an error.", blockConsumer.Error);
						e.AddException("BlockConsumer (" + blockConsumer.Name + ") threw an error.", blockConsumer.Error);
					}
				}
				//if(blockConsumers.Values.Any(bc => bc.Error != null)) return;

				ts.TraceInformation("Writing Logs");
				WriteLogs(e, blockConsumers);

				Ed2k ed2k = null;
				if(blockConsumers.ContainsKey("ED2K")) ed2k = (Ed2k)((HashCalculator)blockConsumers["ED2K"]).HashObj;

				if((switches & eSwitches.OpenInBrowser) != 0 || (switches & eSwitches.PrintAniDBLink) != 0) {
					string aniDBLink = "http://anidb.info/perl-bin/animedb.pl?show=file&size=" + e.File.Length + "&hash=" + BaseConverter.ToString(ed2k.Hash);
					if((switches & eSwitches.OpenInBrowser) != 0) System.Diagnostics.Process.Start(aniDBLink);
					if((switches & eSwitches.PrintAniDBLink) != 0) Console.WriteLine(aniDBLink);
				}
				if((switches & eSwitches.PrintEd2kLink) != 0) Console.WriteLine("ed2k://|file|" + e.File.Name + "|" + e.File.Length + "|" + BaseConverter.ToString(ed2k.Hash) + "|/");
				if((switches & eSwitches.DeleteFileWhenDone) != 0 && e.Exceptions.Count == 0) System.IO.File.Delete(e.File.FullName);
				if((switches & eSwitches.PrintTimeUsedPerFile) != 0) Console.WriteLine("Time elapsed for file: " + (DateTime.Now - startTime).TotalSeconds.ToString() + "s");

				Console.WriteLine(); Console.WriteLine();
			}
		}
Beispiel #4
0
		private static void ProcessMedia(List<string> mediaLst) {
			using(new ActivityTraceContext(ts, "ProcessMedia")) {
				DateTime startedOn = DateTime.Now;
				isProcessing = true;

				var searchOption = switches != eSwitches.ExcludeSubFolders ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;

				long processedBytes = 0, totalBytes;
				sentACReqs = 0;
				failedACReqs = 0;

				ts.TraceInformation("Getting files to process");
#if(PublicRelease)
				var files = GetFiles(mediaLst, searchOption, processExtensions, out totalBytes);
#else
				var files = GetFiles(mediaLst, searchOption, processExtensions, out totalBytes);
#endif

				if(files.Count == 0) {
					ts.TraceInformation("No files to process found");
					Console.WriteLine("No files to process");
				}

				ts.TraceInformation("Creating BlockConsumer cache");
				var container = CreateContainer(blockCount, blockSize);

				FileEnvironment e;
				bool fatalExceptionThrown = false;
				var retryOnIOExCount = retriesOnIOException;
				for(int i = 0;i < files.Count;i++) {
					e = new FileEnvironment(appVersion, container, files[i], startedOn, files.Count, i, totalBytes, processedBytes);
					try {
						ProcessMediaFile(e);
						retryOnIOExCount = retriesOnIOException;
					} catch(FatalException ex) {
						ts.TraceData(TraceEventType.Error, 0, "Fatal error while processing the file.", ex);
						e.AddException("Fatal error while processing the file.", ex);
						fatalExceptionThrown = true;
					} catch(IOException ex) {
						if(--retryOnIOExCount != 0) {
							ts.TraceData(TraceEventType.Error, 0, "File processing failed with an IOException. Retrying...", ex);
							ColoredWriteLine(ConsoleColor.Red, "File processing failed with an IOException. Retrying...", true);
							i--;
						} else {
							ts.TraceData(TraceEventType.Error, 0, "File processing failed " + retriesOnIOException + " times with an IOException. Skipping...", ex);
							ColoredWriteLine(ConsoleColor.Red, "File processing failed " + retriesOnIOException + " times with an IOException. Skipping...", true);
							retryOnIOExCount = retriesOnIOException;
						}

					} catch(Exception ex) {
						ts.TraceData(TraceEventType.Error, 0, "Unhandled error while processing the file.", ex);
						e.AddException("Unhandled error while processing the file.", ex);
					}
					container.Reset();
					processedBytes += e.File.Length;

					if(e.Exceptions.Count != 0) {
						ts.TraceInformation("Processing finished with errors. Logging");
						try {
							var exElem = e.Exceptions.ToXElement(true);
							string exPath = Path.Combine(CurrentDirectory, "Error");
							string exFileName = "Err " + DateTime.Now.ToString("yyyyMMdd HH.mm.ss.ffff") + ".xml";
							if(!Directory.Exists(exPath)) Directory.CreateDirectory(exPath);
							using(var writer = new SafeXmlWriter(Path.Combine(exPath, exFileName), Encoding.Unicode)) exElem.Save(writer);
						} catch(Exception) { }

#if(HasACreq)
						if(username != null && password != null && (switches & eSwitches.NoErrorReporting) == 0) {
							try {
								var exElem = e.Exceptions.ToXElement(false);
								MemoryStream memStream = new MemoryStream();
								using(var writer = new SafeXmlWriter(memStream, Encoding.ASCII)) exElem.Save(writer);

								anidb.CommitError(host, timeout * 1000, "avdumplib", appVersion.Build, username.ToLower(), password, memStream.ToArray());
							} catch(Exception) { }
						}
#endif
					}

					if(fatalExceptionThrown) Environment.Exit(1);

					if((switches & eSwitches.PauseWhenFileDone) != 0) {
						Console.WriteLine("Press any alpha-numeric key to continue");
						Pause();
					}
				}

				isProcessing = false;
				if((switches & eSwitches.PrintTotalTimeUsed) != 0) Console.WriteLine("Total time elapsed: " + (DateTime.Now - startedOn).TotalSeconds + "s");
			}
		}
Beispiel #5
0
		private static void Benchmark() {
			//var bla = new BlockConsumerContainer(16, 4 * 1024 * 1024);
			//bla.RegisterBlockConsumer("MKV", new MatroskaParser("MKV"));
			//bla.AddBlockConsumer("MKV");

			//var watch = new Stopwatch();
			//watch.Start();
			//bla.Start(File.OpenRead(mediaLst[0]));
			//bla.Join();
			//watch.Stop();
			//Console.WriteLine(watch.ElapsedMilliseconds);
			//Console.WriteLine();

			if(mediaLst.Count == 1 && File.Exists(mediaLst[0])) {
				Console.WriteLine("File: " + mediaLst[0]);
				Console.WriteLine("Size: " + (new FileInfo(mediaLst[0]).Length >> 20) + "mb");
				Console.WriteLine("Reading...");
				var fileStream = File.OpenRead(mediaLst[0]);
				var b = new byte[blockSize * 1024];
				var sw = new Stopwatch();
				sw.Start();
				while(fileStream.Read(b, 0, b.Length) != 0) {
					if(sw.Elapsed.Seconds % 2 == 0) { Console.CursorLeft = 0; Console.Write(fileStream.Position * 100 / fileStream.Length + "%"); }
				}
				sw.Stop();
				Console.CursorLeft = 0;
				Console.WriteLine("100%");
				Console.WriteLine("Elapsed: " + sw.Elapsed.TotalSeconds + "s");
				Console.WriteLine("Speed: " + ((new FileInfo(mediaLst[0]).Length >> 20) / sw.Elapsed.TotalSeconds).ToString("0.00") + "mb/s (may be inaccurate due to read caching)");
				Console.WriteLine();
			}

			var container = CreateContainer(blockCount, blockSize);
			Dictionary<string, IBlockConsumer> blockConumsers;
			var e = new FileEnvironment(null, container, null, DateTime.Now, 1, 0, 4 * 1024 * 1024 * 1024L, 0);


			ExecuteBlockConsumers(e, out blockConumsers, new NullStream(e.TotalBytes));
			Pause(true);
		}
Beispiel #6
0
		private static InfoProviderBase CreateInfoProvider(FileEnvironment e, Dictionary<string, IBlockConsumer> blockConsumers, out bool noErrors) { //TODO: Refactor
			using(new ActivityTraceContext(ts, "CreateInfoProvider")) {
				MatroskaProvider mkvProvider = null;
				OgmOggProvider ogmOggProvider = null;
				MediaInfoProvider milProvider = null;
				HashInfoProvider hashProvider = null;
				FileExtensionProvider extProvider = null;
				//CompositeInfoProvider p = null;

				noErrors = true;

				try {
					if(blockConsumers.ContainsKey("Matroska")) {
						var matroskaFile = ((MatroskaParser)blockConsumers["Matroska"]).MatroskaFileObj;
						if(matroskaFile != null) mkvProvider = new MatroskaProvider(matroskaFile);
						ts.TraceInformation("Added Matroska Provider");
					}
				} catch(Exception ex) { e.AddException("Failed to create MatroskaProvider", ex); noErrors = false; }

				try {
					if(blockConsumers.ContainsKey("Ogm/Ogg")) {
						var ogmOggFile = ((OgmOggParser)blockConsumers["Ogm/Ogg"]).OgmOggFileObj;
						if(ogmOggFile != null) ogmOggProvider = new OgmOggProvider(ogmOggFile);
						ts.TraceInformation("Added Ogm/Ogg Provider");
					}
				} catch(Exception ex) { e.AddException("Failed to create OgmOggProvider", ex); noErrors = false; }

				try {
					extProvider = new FileExtensionProvider(e.File.FullName);
					ts.TraceInformation("Added FileExtensionProvider Provider");
				} catch(Exception ex) { e.AddException("Failed to create FileExtensionProvider", ex); /*noErrors = false;*/ }

				try {
					milProvider = new MediaInfoProvider(e.File.FullName);
					ts.TraceInformation("Added MediaInfoLib Provider");
				} catch(FatalException ex) {
					throw;
				} catch(Exception ex) {
					e.AddException("Failed to create MediaInfoProvider", ex); noErrors = false;
				}

				try {
					hashProvider = new HashInfoProvider(blockConsumers.Values.OfType<HashCalculator>());
					ts.TraceInformation("Added Hash Provider");
				} catch(Exception ex) { e.AddException("Failed to create HashInfoProvider", ex); noErrors = false; }


				var providers = new Collection<InfoProviderBase>();
				if(mkvProvider != null) providers.Add(mkvProvider);
				if(ogmOggProvider != null) providers.Add(ogmOggProvider);
				if(extProvider != null) providers.Add(extProvider);
				if(milProvider != null) providers.Add(milProvider);
				if(hashProvider != null) providers.Add(hashProvider);

				return new CompositeInfoProvider(providers);
			}
		}
Beispiel #7
0
		private static void DisplayBuffer(FileEnvironment e, BlockConsumerContainer.Progress progress) {
			double bufferSize = 0; int charCount = 0; long bytesProcessed = 0;
			int lastLineIndex = 0, maxNameLength = 0;
			long fileSize = e.File == null ? e.TotalBytes : e.File.Length;
			int consoleWidth = Console.BufferWidth != 0 ? Console.BufferWidth : (Console.WindowWidth != 0 ? Console.WindowWidth : 80);

			string output;

			Average[] mean = null;
			if(progress != null) {
				mean = new Average[progress.BlockConsumerCount];
				for(int i = 0;i < mean.Length;i++) mean[i] = new Average();
				for(int i = 0;i < progress.BlockConsumerCount;i++) if(maxNameLength < progress.Name(i).Length) maxNameLength = progress.Name(i).Length + 1;
				if(maxNameLength < "Progress".Length) maxNameLength = "Progress".Length;

				CursorVisible = false;
				output = "Bar: Buffer usage | blocksize: " + blockSize + "KB | blockCount: " + blockCount + "\n";

				for(int i = 0;i < progress.BlockConsumerCount;i++) {
					output += progress.Name(i).PadRight(maxNameLength + 1) + "[" + "".PadRight(consoleWidth - maxNameLength - 4) + "]\n";
				}
				output += "\n" + "Progress".PadRight(maxNameLength + 1) + "[" + "".PadRight(consoleWidth - maxNameLength - 4) + "]\n\n\n";

				Console.Write(output);
			}

			lastLineIndex = Console.CursorTop;

			bool doLoop;
			int barLength = consoleWidth - maxNameLength - 4;
			do {
				doLoop = progress != null && !progress.HasFinished;

				if(progress != null) {
					bytesProcessed = 0;
					for(int i = 0;i < progress.BlockConsumerCount;i++) {
						mean[i].Add(progress.BlockCount(i));
						bufferSize = mean[i].Calc(10);
						if(bytesProcessed > progress.ProcessedBytes(i) || bytesProcessed == 0) bytesProcessed = progress.ProcessedBytes(i);

						charCount = bufferSize != 0 ? (int)((bufferSize / (double)blockCount) * barLength) : 0;
						charCount = progress.ProcessedBytes(i) == fileSize ? 0 : charCount;

						Console.SetCursorPosition(maxNameLength + 2, lastLineIndex - progress.BlockConsumerCount + i - 4);
						Console.Write("".PadLeft(charCount, '*') + "".PadRight(barLength - charCount, ' '));
					}
					Console.SetCursorPosition(maxNameLength + 2, lastLineIndex - 3);
					charCount = fileSize != 0 ? (int)((double)bytesProcessed / (double)fileSize * barLength) : barLength;
					Console.WriteLine("".PadLeft(charCount, '*') + "".PadRight(barLength - charCount, ' '));



					output =
					  "Position: " + (bytesProcessed >> 20).ToString().PadLeft(3) + "MB/" + (fileSize >> 20) + "MB  " +
					  "Elapsed time: " + progress.TimeElapsed.ToFormatedString() + " " +
					  "Speed: " + Math.Max((int)((bytesProcessed >> 20) / progress.TimeElapsed.TotalSeconds), 0) + "MB/s";

					output += "".PadLeft(output.Length < consoleWidth ? consoleWidth - output.Length - 1 : 0, ' ');
					Console.WriteLine(output);
				} else {
					bytesProcessed = fileSize;
				}

				bytesProcessed += e.ProcessedBytes;
				var totalTimeElapsed = DateTime.Now - e.StartedOn;
				var eta = e.TotalBytes * (totalTimeElapsed.TotalSeconds / bytesProcessed) - totalTimeElapsed.TotalSeconds + 0.5;
				if(!double.IsInfinity(eta)) {
					output =
					  "Files: " + (e.ProcessedFiles + 1) + "/" + e.TotalFiles + " " +
					  "Bytes: " + (bytesProcessed >> 20) + "MB/" + (e.TotalBytes >> 20) + "MB " +
					  "Elapsed: " + totalTimeElapsed.ToFormatedString() + " " +
					  "ETA: " + TimeSpan.FromSeconds(eta).ToFormatedString();
					//output += "".PadLeft(output.Length < consoleWidth ? consoleWidth - output.Length - 1 : 0, ' ');
					Console.WriteLine(output.PadRight(consoleWidth - 1));
				}

#if(HasACreq)
				if(anidb != null) {
					output = "ACReq( Done: " + sentACReqs + " Todo: " + (e.TotalFiles - sentACReqs - failedACReqs - anidb.UnsentQueryCount) + " Failed: " + failedACReqs + " Pending: " + anidb.UnsentQueryCount + " )";
					Console.Write(output.PadRight(consoleWidth - 1));
				}
#endif

				if(doLoop) Thread.Sleep(80);
			} while(doLoop);


			if(progress != null) {
				for(int i = 0;i < progress.BlockConsumerCount;i++) {
					Console.SetCursorPosition(maxNameLength + 2, lastLineIndex - progress.BlockConsumerCount + i - 4);
					Console.Write(progress.BlockConsumerObj(i).ToString());
				}
				Console.SetCursorPosition(0, lastLineIndex);

			}
			Console.WriteLine();
			CursorVisible = true;
		}