/// <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();
            }
        }
예제 #2
0
        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}");
        }
예제 #4
0
        //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);
        }