/// <summary> /// Handles the event of the computer memory being filled with loaded prime numbers. /// </summary> /// <param name="result">The loading result container.</param> /// <param name="lastResultFile">The last result file.</param> /// <returns>The loading result container.</returns> private static ExistingPrimesLoadingResult handleMemoryOverflow(ExistingPrimesLoadingResult result, string lastResultFile) { result.MemoryLimitReached = true; //There was a number when the result files were generated. //That number was the next in line to be checked if it was a prime number. //Find that number again. var lastPrime = File .ReadLines(lastResultFile) .Select(l => BigInteger.Parse(l)) .LastOrDefault(); var nextNumberToCheck = lastPrime + 1; //The next number to check we calculated from the last prime in the last file should be bigger or equal //to the corresponding number in the result container, otherwise somethings are wrong with the result files. if (nextNumberToCheck < result.NextNumberToCheck) { var message = "Calculation indicates corrupted result files. Make sure all result files exists and that the prime numbers within are sorted ascending."; throw new InvalidOperationException(message); } result.NextNumberToCheck = nextNumberToCheck; return(result); }
/// <summary> /// Fetches prime numbers from existing result files. /// </summary> /// <param name="indexedResultFiles">All the result files accompanied with their index.</param> /// <returns>Container holding information about the loaded prime numbers.</returns> private ExistingPrimesLoadingResult fetchPrimes(SortedDictionary <int, string> indexedResultFiles) { var result = new ExistingPrimesLoadingResult(); var resultFiles = indexedResultFiles .Select(f => f.Value) .ToList(); var lastResultFile = resultFiles.LastOrDefault(f => File.ReadLines(f).Any()); for (int i = 0; i < resultFiles.Count; i++) { var loadingArgs = new PrimesLoadingFromFile(i, resultFiles.Count); OnLoadingPrimesFromFile?.Invoke(this, loadingArgs); var subPrimes = File .ReadLines(resultFiles[i]) .Select(l => BigInteger.Parse(l)); //Verify that the file contained any prime numbers. if (subPrimes.Any()) { //Calculate the next number to check if it's a prime number. result.NextNumberToCheck = subPrimes.Last() + 1; } else { //TODO: Test this use case. return(result); } //Store the loaded primes. result = storeSubPrimesInMemory(result, subPrimes, lastResultFile); //There's no use in loading any more primes if the memory is full. if (result.MemoryLimitReached) { return(result); } //Check if the user cancelled the execution. if (userPressedEscape()) { result.ExecutionWasAborted = true; return(result); } } return(result); }
/// <summary> /// Adds the loaded sub primes to the container holding all the loaded prime numbers. /// </summary> /// <param name="result">The loading result container.</param> /// <param name="subPrimes">The prime numbers to add to the container.</param> /// <param name="lastResultFile">The last result file.</param> /// <returns>The loading result container.</returns> private static ExistingPrimesLoadingResult storeSubPrimesInMemory(ExistingPrimesLoadingResult result, IEnumerable <BigInteger> subPrimes, string lastResultFile) { try { result.CachedPrimes.AddRange(subPrimes); } catch (OutOfMemoryException ex) { if (Tools.MemoryIsFilledWithPrimes(ex)) { return(handleMemoryOverflow(result, lastResultFile)); } throw; } return(result); }