//Check for PoC1 filename private static bool IsOptimizedPOC1PlotFileName(string filename) { Regex rgx = new Regex(@"(.)*\d+(_)\d+(_)\d+(_)\d+$"); if (rgx.IsMatch(filename)) { Plotfile temp = ParsePlotFileName(filename); return(temp.stagger == temp.nonces ? true : false); } else { return(false); } }
static void Main(string[] args) { AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit); //no arguments provided if (args.Length < 2) { System.Console.WriteLine("Plotmerge v.1.4"); System.Console.WriteLine("Syntax: plotMerge source target [memlimit] \n"); System.Console.WriteLine("source\t\t Optmized Plot File Source (can be POC1 or POC2)"); System.Console.WriteLine("target\t\t Optmized Plot File Target (can be POC1 or POC2)\n"); System.Console.WriteLine("memlimit\t optional memory limit in MB (default:1024, maximum:8192)\n"); System.Console.WriteLine("Example:\t plotMerge XXXXXXXXXXXXXXXXXXXX_2000_1000_1000 XXXXXXXXXXXXXXXXXXXX_0_10000"); System.Console.WriteLine("\t\t writes nonces 2000-2999 from source file to target file and converts to poc2 on-the-fly"); return; } //read arguments String source = args[0]; String target = args[1]; int memlimit; if (args.Length == 3) { bool test = int.TryParse(args[2], out memlimit); if (test == false) { Console.Error.WriteLine("ERR: invalid input for memlimit!"); return; } //enfore a limit slightly lower than maximum to avoid int overflows memlimit = Math.Min(memlimit, 8184); } else { memlimit = 1024; } //check mergeability //plot file names valid, size of plotfiles valid, source file nonces part of target file nonces Boolean spoc2; //source is POC2 Boolean tpoc2; //target is POC2 Boolean shuffle; //Poc1Poc2 shuffling needed //check plot file names if (IsOptimizedPOC1PlotFileName(source)) { spoc2 = false; } else { if (IsOptimizedPOC2PlotFileName(source)) { spoc2 = true; } else { Console.Error.WriteLine("ERR: source file format not recognized!"); return; } } if (IsOptimizedPOC1PlotFileName(target)) { tpoc2 = false; } else { if (IsOptimizedPOC2PlotFileName(target)) { tpoc2 = true; } else { Console.Error.WriteLine("ERR: target file format not recognized!"); return; } } shuffle = (spoc2 != tpoc2); Plotfile src = ParsePlotFileName(source); Plotfile tar = ParsePlotFileName(target); System.Console.WriteLine("INFO: source Plot File: starting Nonce: " + src.start.ToString() + ", last Nonce: " + (src.start + (uint)src.nonces - 1).ToString() + ", #nonces: " + src.nonces.ToString() + ", POC" + (spoc2 ? "2" : "1")); System.Console.WriteLine("INFO: target Plot File: starting Nonce: " + tar.start.ToString() + ", last Nonce: " + (tar.start + (uint)tar.nonces - 1).ToString() + ", #nonces: " + tar.nonces.ToString() + ", POC" + (tpoc2 ? "2" : "1")); if (shuffle) { System.Console.WriteLine("INFO: POC1POC2 Shuffling activated."); } //check matching ID if (src.id != tar.id) { Console.Error.WriteLine("ERR: numeric ID of source and target file not matching!"); return; } //check source file existance and filesizes if (System.IO.File.Exists(source)) { long length = new System.IO.FileInfo(source).Length; if (length != (long)src.nonces * (2 << 17)) { Console.Error.WriteLine("ERR: actual source file size not matching file name implied size!"); return; } } else { Console.Error.WriteLine("ERR: soure file not found!"); return; } //if target file doesnt exist, filespace needs to be preallocated bool prealloc = false; if (System.IO.File.Exists(target)) { long length = new System.IO.FileInfo(target).Length; if (length != (long)tar.nonces * (2 << 17)) { Console.Error.WriteLine("ERR: actual target file size not matching file name implied size!"); return; } } else { prealloc = true; System.Console.WriteLine("INFO: new target file will be created!"); } //check inclusion if (src.start < tar.start || src.start + (uint)src.nonces - 1 > tar.start + (uint)tar.nonces - 1) { Console.Error.WriteLine("ERR: source file noncesnot part of target file nonces!"); return; } //do it! // calc maximum nonces to read (limit) int limit = Convert.ToInt32(memlimit) * 4096; //allocate memory Scoop scoop1 = new Scoop(Math.Min(src.nonces, limit)); //space needed for one partial scoop Scoop scoop2 = new Scoop(Math.Min(src.nonces, limit)); //space needed for one partial scoop Scoop scoop3 = new Scoop(Math.Min(src.nonces, limit)); //space needed for one partial scoop Scoop scoop4 = new Scoop(Math.Min(src.nonces, limit)); //space needed for one partial scoop //check if sectors and nonces are aligned for easy direct I/O Boolean dio = true; int SectorsPerCluster; int BytesPerSectorA; int BytesPerSectorB; int NumberOfFreeClusters; int TotalNumberOfClusters; FileInfo file = new FileInfo(source); DriveInfo drive = new DriveInfo(file.Directory.Root.FullName); GetDiskFreeSpace(drive.Name, out SectorsPerCluster, out BytesPerSectorA, out NumberOfFreeClusters, out TotalNumberOfClusters); file = new FileInfo(target); drive = new DriveInfo(file.Directory.Root.FullName); GetDiskFreeSpace(drive.Name, out SectorsPerCluster, out BytesPerSectorB, out NumberOfFreeClusters, out TotalNumberOfClusters); if (ddio || (src.nonces % (BytesPerSectorA / 64) != 0) || (tar.nonces % (BytesPerSectorB / 64) != 0)) { dio = false; } //create and open Reader/Writer scoopReadWriter1 = new ScoopReadWriter(source); scoopReadWriter2 = new ScoopReadWriter(target); if (!(scoopReadWriter1.OpenR(dio) && scoopReadWriter2.OpenW(dio))) { return; } ; //preallocate disk space if (prealloc) { if (!scoopReadWriter2.PreAlloc(tar.nonces)) { return; } } //initialise stats DateTime start = DateTime.Now; TimeSpan elapsed; TimeSpan togo; //create masterplan int loops = (int)Math.Ceiling((double)(src.nonces) / limit); TaskInfo[] masterplan = new TaskInfo[2048 * loops]; for (int y = 0; y < 2048; y++) { int zz = 0; //loop partial scoop for (int z = 0; z < src.nonces; z += limit) { masterplan[y * loops + zz] = new TaskInfo(); masterplan[y * loops + zz].reader = scoopReadWriter1; masterplan[y * loops + zz].writer = scoopReadWriter2; masterplan[y * loops + zz].y = y; masterplan[y * loops + zz].z = z; masterplan[y * loops + zz].x = y * loops + zz; masterplan[y * loops + zz].limit = limit; masterplan[y * loops + zz].src = src; masterplan[y * loops + zz].tar = tar; masterplan[y * loops + zz].scoop1 = scoop1; masterplan[y * loops + zz].scoop2 = scoop2; masterplan[y * loops + zz].scoop3 = scoop3; masterplan[y * loops + zz].scoop4 = scoop4; masterplan[y * loops + zz].shuffle = shuffle; masterplan[y * loops + zz].end = masterplan.LongLength; zz += 1; } } //work masterplan //perform first read Th_read(masterplan[0]); autoEvents = new AutoResetEvent[] { new AutoResetEvent(false), new AutoResetEvent(false) }; //perform reads and writes parallel for (long x = 1; x < masterplan.LongLength; x++) { ThreadPool.QueueUserWorkItem(new WaitCallback(Th_write), masterplan[x - 1]); ThreadPool.QueueUserWorkItem(new WaitCallback(Th_read), masterplan[x]); WaitHandle.WaitAll(autoEvents); if (halt1 || halt2) { Console.Error.WriteLine("ERR: Shutting down!"); return; } //update status elapsed = DateTime.Now.Subtract(start); togo = TimeSpan.FromTicks(elapsed.Ticks / (masterplan[x].y + 1) * (2048 - masterplan[x].y - 1)); string completed = Math.Round((double)(masterplan[x].y + 1) / 2048 * 100).ToString() + "%"; string speed1 = Math.Round((double)src.nonces / 4096 * 2 * (masterplan[x].y + 1) * 60 / (elapsed.TotalSeconds + 1)).ToString() + " nonces/m "; string speed2 = "(" + (Math.Round((double)src.nonces / (2 << 12) * (masterplan[x].y + 1) / (elapsed.TotalSeconds + 1))).ToString() + "MB/s)"; string speed = speed1 + speed2; Console.Write("Completed: " + completed + ", Elapsed: " + TimeSpanToString(elapsed) + ", Remaining: " + TimeSpanToString(togo) + ", Speed: " + speed + " \r"); } //perform last write if (!halt1 && !halt2) { Th_write(masterplan[masterplan.LongLength - 1]); } if (halt1 || halt2) { Console.Error.WriteLine("ERR: Shutting down!"); return; } // close reader/writer scoopReadWriter1.Close(); scoopReadWriter2.Close(); Console.Write("All done!"); }