/// <summary> /// Takes in file 1 and 2 and uses their byte offsets to write their (4) bytes to each other (Cb1 and Cb2) /// </summary> /// <param name="file1">File Directory 1</param> /// <param name="file2">File Directory 2</param> /// <param name="off1">Byte offset for file1</param> /// <param name="off2">Byte offset for file2</param> /// <param name="chunkBytes1"></param> /// <param name="chunkBytes2"></param> public static async Task SwapBytes(string file1, string file2, int off1, int off2, byte[] chunkBytes1, byte[] chunkBytes2) { RegionDiscriminator(file1, file2); AsyncLogger.WriteLine($"Swapping chunks bytes at {file1}:{off1} with {file2}:{off2}"); if (file1 != file2) { await using var fileStream1 = File.OpenWrite(file1); await using var fileStream2 = File.OpenWrite(file2); await using var binaryWriter1 = new BinaryWriter(fileStream1); await using var binaryWriter2 = new BinaryWriter(fileStream2); fileStream1.Seek(off1, 0); fileStream2.Seek(off2, 0); binaryWriter1.Write(chunkBytes2); binaryWriter2.Write(chunkBytes1); await fileStream1.FlushAsync(); await fileStream2.FlushAsync(); } else { await using var fileStream1 = File.OpenWrite(file1); await using var binaryWriter1 = new BinaryWriter(fileStream1); fileStream1.Seek(off1, 0); binaryWriter1.Write(chunkBytes2); await fileStream1.FlushAsync(); } }
private static ChunkPair InitializeInputVariables() { AsyncLogger.WriteLine("All Good"); AsyncLogger.WriteLine("What is chunk X1?"); var inX1 = Convert.ToInt32(Console.ReadLine()); AsyncLogger.WriteLine("What is chunk Z1?"); var inZ1 = Convert.ToInt32(Console.ReadLine()); AsyncLogger.WriteLine("What is chunk X2?"); var inX2 = Convert.ToInt32(Console.ReadLine()); AsyncLogger.WriteLine("What is chunk Z2?"); var inZ2 = Convert.ToInt32(Console.ReadLine()); return(Calc.ChunkCalcFromChunkCoords(inX1, inZ1, inX2, inZ2)); }
/// <summary> /// Discriminates to see if both region files are the same and writes one or both of them depending on the case /// </summary> /// <param name="file1">File Location 1</param> /// <param name="file2">File Location 2</param> private static void RegionDiscriminator(string file1, string file2) { var timeBackupFormat = $"{DateTime.Now.Day}-${DateTime.Now.Hour}-{DateTime.Now.Minute}" + $"-{DateTime.Now.Second}.backup"; AsyncLogger.WriteLine($"Creating backup for {file1} {file2}"); if (file1 == file2) { File.Copy(file1, $"{file1}-{timeBackupFormat}", true); } else { File.Copy(file2, $"{file2}-{timeBackupFormat}", true); File.Copy(file1, $"{file1}-{timeBackupFormat}", true); } AsyncLogger.WriteLine($"Finished backup for {file1} {file2}"); }
//TODO Add support for giving a text file as input and reading all chunks from there private static async Task Main(string[] args) { var stopwatch = new Stopwatch(); AsyncLogger.WriteLine("Systems are go"); var chunkPairs = new List <ChunkPair>(); string fileWorld; if (args.Length > 0) { // Read a text file // For now only support for the first line stopwatch.Start(); var file = args[0]; if (!File.Exists(file)) { throw new FileNotFoundException($"Unable to find the file {file}"); } (fileWorld, chunkPairs) = await FileManager.GetChunkSwapList(args[0]); } else { fileWorld = "."; chunkPairs.Add(InitializeInputVariables()); stopwatch.Start(); } var tasks = new List <Task>(); foreach (var chunkPair in chunkPairs) { var calcData1 = chunkPair.chunk1; var calcData2 = chunkPair.chunk2; AsyncLogger.WriteLine($"{calcData1.byteOff} {calcData2.byteOff}"); string rf1; string rf2; (rf1, rf2) = FileManager.DirFind(fileWorld, calcData1.regionX, calcData1.regionZ, calcData2.regionX, calcData2.regionZ); tasks.Add(Task.Run(async() => { var lock1 = GetLock(rf1); // Will be by default the already created lock or a new one. var lock2 = GetLock(rf2); // Will be by default the already created lock or a new one. if (lock1 == null) { if (lock2 != null) { lock1 = lock2; } else { lock1 = new object(); } lock1 = AddLock(rf1, lock1); } if (lock2 == null) { lock2 = lock1; lock2 = AddLock(rf2, lock2); } // Lock the file to avoid writing to the same file at the same time Task t; lock (lock1) { lock (lock2) { t = ByteSwapper.ReadAndSwapBytes(rf1, rf2, calcData1.byteOff, calcData2.byteOff); } } // Wait for task to finish. await t; })); } // Wait for tasks to finish while (tasks.Count > 0) { var taskListCopy = new List <Task>(tasks); foreach (var task in taskListCopy) { await task; tasks.Remove(task); } } AsyncLogger.WriteLine($"Operation Completed. Took {stopwatch.ElapsedMilliseconds}ms"); //TODO Ability to go back and do another chunk without having the program close on you stopwatch.Stop(); Console.ReadLine(); AsyncLogger.StopThread(); Environment.Exit(0); }
public static async Task <(string worldLine, List <ChunkPair>)> GetChunkSwapList(string file) { using var fileStream = File.OpenText(file); var worldLine = await fileStream.ReadLineAsync(); if (worldLine == null) { throw new FormatException( $"Missing world('the_word') statement at beginning of file file {file}. The world parameter must be a folder directory that is accesible"); } var worldRegex = new Regex("world\\(\"(.*)\"\\)"); var worldMatch = worldRegex.Match(worldLine); if (worldMatch.Groups.Count == 0) { throw new FormatException($"World line ({worldLine}) does not match world regex ({worldRegex})."); } worldLine = worldMatch.Groups[1].Value; var worldPath = Path.GetFullPath(worldLine, Path.GetDirectoryName(Path.GetFullPath(file)) ?? throw new InvalidOperationException()); if (!Directory.Exists(worldPath)) { throw new FileNotFoundException($"Could not find directory {worldPath}"); } var regionPath = Path.GetFullPath("region", worldPath); if (Directory.Exists(regionPath)) // Check if the folder contains a "region" folder, if so use that instead. { worldPath = Path.GetFullPath("region", worldPath); } AsyncLogger.WriteLine($"Using world folder {worldPath}"); var chunkPairs = new List <ChunkPair>(); while (!fileStream.EndOfStream) { var fileLine = await fileStream.ReadLineAsync(); if (fileLine == "") { continue; } try { var pair = ParseLine(fileLine); chunkPairs.Add(pair); } catch (Exception e) { throw new Exception($"Unable to parse {fileLine}.", e); } } fileStream.Close(); return(worldPath, chunkPairs); }