コード例 #1
0
        public async Task Process()
        {
            var currentDestinationIndex = 0;
            var uniqueOutputs           = new Dictionary <string, ChiaPlotOutput>();
            var outputChannel           = Channel.CreateUnbounded <ChiaPlotOutput>();
            var ignoredDrives           = new List <string>();
            var staticText = new StringBuilder();
            var maxParallelPlotsPerStagger = 1;

            // initialization process to start 2 plots per temp drive
            // don't ignore plot drives but do check plot drives are not on the ignoreDrives list.  This will allow us to have the same temp and dest drive and ignore when full.
// where do I add the logic to stagger?
            foreach (var tempDrive in chiaPlotManagerContextConfiguration.TempPlotDrives)
            {
                var destinations = new List <string>();
                while (destinations.Count < maxParallelPlotsPerStagger)
                {
                    var destination = chiaPlotManagerContextConfiguration.DestinationPlotDrives.Skip(currentDestinationIndex).FirstOrDefault();
                    if (destination == null)
                    {
                        currentDestinationIndex = 0;
                        destination             = chiaPlotManagerContextConfiguration.DestinationPlotDrives.Skip(currentDestinationIndex).First();
                    }
                    destinations.Add(destination);
                    currentDestinationIndex++;
                }
                var innerForEachBreaker = false;
                foreach (var dest in destinations)
                {
                    if (innerForEachBreaker)
                    {
                        continue;
                    }

                    var process = await startProcess(dest, tempDrive);

                    if (process != null)
                    {
                        var first = await process.Reader.ReadAsync();

                        if (!string.IsNullOrWhiteSpace(first.InvalidDrive))
                        {
                            if (first.InvalidDrive == tempDrive && tempDrive != dest)
                            {
                                innerForEachBreaker = true;
                                continue;
                            }

                            if (!ignoredDrives.Any(id => id == first.InvalidDrive))
                            {
                                ignoredDrives.Add(first.InvalidDrive);
                            }
                        }
                        else
                        {
                            await foreach (var value in process.Reader.ReadAllAsync())
                            {
                                if (!string.IsNullOrWhiteSpace(value.Id))
                                {
                                    uniqueOutputs[value.Id] = value;
                                    break;
                                }
                            }
                            Task task = Task.Run(async() => {
                                await foreach (var value in process.Reader.ReadAllAsync())
                                {
                                    await outputChannel.Writer.WriteAsync(value);
                                }
                            });
                        }
                    }
                }
            }

            // watching process that keeps at least 2 running and will start one when transfer starts

            var keepRunning = true;

            while (keepRunning)
            {
                await foreach (var output in outputChannel.Reader.ReadAllAsync())
                {
                    if (string.IsNullOrWhiteSpace(output.Id))
                    {
                        continue;
                    }
                    if (output.Id == "static")
                    {
                        staticText.AppendLine(output.Output);
                        continue;
                    }
                    uniqueOutputs[output.Id] = output;
                    var outputs = uniqueOutputs.Values;
                    if (output.IsTransferError)
                    {
                        // add destination to ignored
                        var process = processRepo.GetAll().Where(p => p.Id == output.ProcessId).FirstOrDefault();
                        process.Kill(true);
                        process.Close();

                        if (!ignoredDrives.Any(id => id == output.DestinationDrive))
                        {
                            ignoredDrives.Add(output.DestinationDrive);
                        }

                        // start new transfer process to alternative destination
                        foreach (var destination in chiaPlotManagerContextConfiguration.DestinationPlotDrives)
                        {
                            //var tempFile = Path.Combine(output.TempDrive, $"{output.Id}");
                            if (!ignoredDrives.Any(id => id == destination))
                            {
                                var driveInfo    = new DriveInfo(destination);
                                var tempFileName = Directory.GetFiles(output.TempDrive, output.Id).FirstOrDefault();

                                if (string.IsNullOrEmpty(tempFileName))
                                {
                                    // throw?
                                }
                                var tempFile = new FileInfo(tempFileName);
                                if (driveInfo.AvailableFreeSpace > tempFile.Length)
                                {
                                    var trimmedFileName = tempFileName.Substring(tempFileName.IndexOf("plot-k"));
                                    trimmedFileName = trimmedFileName.Substring(0, trimmedFileName.IndexOf(".plot.") + 5);
                                    tempFile.MoveTo(Path.Combine(destination, trimmedFileName), true);
                                    break;
                                }
                            }
                        }

                        output.IsTransferError = false;
                    }

                    if (!ignoredDrives.Any(d => d == output.DestinationDrive || d == output.TempDrive))
                    {
                        var startNewProcess = false;
                        var related         = outputs.Where(o => o.TempDrive == output.TempDrive);
                        var completed       = related.Where(o => o.IsPlotComplete);
                        var remaining       = related.Where(o => !o.IsPlotComplete);

                        //1) where get all remaining that is transfering and do not count those
                        if (remaining.Count() < chiaPlotManagerContextConfiguration.PlotsPerDrive &&
                            remaining
                            .Where(o => string.IsNullOrWhiteSpace(o.CurrentPhase) || (o.CurrentPhase == "1" || o.CurrentPhase == "2"))
                            .Count() < maxParallelPlotsPerStagger &&
                            completed.Where(c => c.IsTransferComplete == false).Count() < chiaPlotManagerContextConfiguration.PlotsPerDrive)
                        {
                            startNewProcess = true;
                        }

                        if (startNewProcess)
                        {
                            var process = await startProcess(output.DestinationDrive, output.TempDrive);

                            var first = await process.Reader.ReadAsync();

                            if (!string.IsNullOrWhiteSpace(first.InvalidDrive))
                            {
                                if ((first.InvalidDrive == first.TempDrive && first.TempDrive != first.DestinationDrive) &&
                                    (!ignoredDrives.Any(id => id == first.InvalidDrive)))
                                {
                                    ignoredDrives.Add(first.InvalidDrive);
                                }
                            }
                            else
                            {
                                // await outputChannel.Writer.WriteAsync(new ChiaPlotOutput { Id = "static", Output = "started new plot"});
                                await foreach (var value in process.Reader.ReadAllAsync())
                                {
                                    if (!string.IsNullOrWhiteSpace(value.Id))
                                    {
                                        uniqueOutputs[value.Id] = value;
                                        break;
                                    }
                                }
                                Task task = Task.Run(async() => {
                                    await foreach (var value in process.Reader.ReadAllAsync())
                                    {
                                        await outputChannel.Writer.WriteAsync(value);
                                    }
                                });
                                break;
                            }
                        }
                    }

                    var ignoredDrivesOutput = new StringBuilder();
                    ignoredDrivesOutput.Append("Ingored Drives: ");
                    ignoredDrivesOutput.AppendJoin(',', ignoredDrives);
                    ignoredDrivesOutput.AppendLine(staticText.ToString());
                    allOutputsDelegate.Invoke(outputs, ignoredDrivesOutput);
                }
                keepRunning = (chiaPlotManagerContextConfiguration.TempPlotDrives.All(t => ignoredDrives.Any(i => i == t)) || chiaPlotManagerContextConfiguration.DestinationPlotDrives.All(t => ignoredDrives.Any(i => i == t))) == false;

                if (!keepRunning)
                {
                    Console.WriteLine("WHY?");
                }
            }
        }