// Spludlow Software // Copyright © Samuel P. Ludlow 2020 All Rights Reserved // Distributed under the terms of the GNU General Public License version 3 // Distributed WITHOUT ANY WARRANTY; without implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE // https://www.spludlow.co.uk/LICENCE.TXT // The Spludlow logo is a registered trademark of Samuel P. Ludlow and may not be used without permission // v1.14 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Security.Cryptography; namespace Spludlow.Io { /// /// Make random test binary files, entire contents is random (no headers or anything). /// Note these files will not compress with any gain. /// public class TestFiles { [ThreadStatic] private static Random _Random = null; private static object _RandomLock = new object(); private static int _RandomSeed = 0; /// /// Must be called by each thread to use _Random /// Ensures each thread's Random will have a unique seed /// private static void RandomInitialize() { if (_Random != null) return; lock (_RandomLock) { _Random = new Random(_RandomSeed++); } } /// /// Make random test data file /// public static ulong Make(string filename, ulong bytes) { RandomInitialize(); int bufferSize = 128 * 1024 * 1024; byte[] buffer = new byte[bufferSize]; ulong remaining = bytes; using (FileStream stream = new FileStream(filename, FileMode.Create)) { while (remaining > 0) { ulong todo = remaining; if (todo > (ulong)buffer.Length) todo = (ulong)buffer.Length; _Random.NextBytes(buffer); stream.Write(buffer, 0, (int)todo); remaining -= todo; } } return bytes; } public static ulong MakeGiga(string filename, decimal gigabytes) { return Make(filename, (ulong)(gigabytes * 1024 * 1024 * 1024)); } public static ulong MakeMega(string filename, decimal megabytes) { return Make(filename, (ulong)(megabytes * 1024 * 1024)); } public static ulong MakeKilo(string filename, decimal kilobytes) { return Make(filename, (ulong)(kilobytes * 1024)); } /// /// Rain down random test files to a directory keeping them locked upto a specifed time /// Files are named with the SHA1 in the name /// public static void DirectoryWritesSHA1(string directory, int threads, int threadFileCount, int minMeg, int maxMeg, int maxSleepSeconds) { Task[] tasks = new Task[threads]; for (int index = 0; index < threads; ++index) { int threadId = index; tasks[index] = new Task(() => DirectoryWritesSHA1Worker(directory, threadId, threadFileCount, minMeg, maxMeg, maxSleepSeconds)); } foreach (Task task in tasks) task.Start(); Task.WaitAll(tasks); } private static void DirectoryWritesSHA1Worker(string directory, int threadId, int threadFileCount, int minMeg, int maxMeg, int maxSleepSeconds) { RandomInitialize(); int diffMeg = maxMeg - minMeg; using (Spludlow.TempDirectory tempDir = new Spludlow.TempDirectory()) { string tempFilename = tempDir.Path + @"\file.dat"; for (int fileId = 0; fileId < threadFileCount; ++fileId) { int meg = minMeg + _Random.Next(diffMeg); int sleepSeconds = _Random.Next(maxSleepSeconds); string hash = MakeSHA1Mega(tempFilename, meg); string targetFilename = directory + @"\" + threadId.ToString("0000") + "-" + fileId.ToString("0000") + "-" + meg.ToString("0000") + "mb-" + sleepSeconds.ToString("0000") + "s-" + hash + ".dat"; if (maxSleepSeconds == 0) File.Copy(tempFilename, targetFilename); else CopySlow(tempFilename, targetFilename, sleepSeconds); File.Delete(tempFilename); } } } /// /// Crate a random test data file and return the SHA1 hash while doing it /// public static string MakeSHA1(string filename, ulong filesize) { RandomInitialize(); int bufferSize = 128 * 1024 * 1024; byte[] buffer = new byte[bufferSize]; using (SHA1 hash = new SHA1Managed()) { using (FileStream stream = new FileStream(filename, FileMode.CreateNew, FileAccess.Write)) { using (CryptoStream cryStream = new CryptoStream(stream, hash, CryptoStreamMode.Write)) { while (filesize > 0) { ulong writeSize = (filesize < (ulong)buffer.Length ? filesize : (ulong)buffer.Length); _Random.NextBytes(buffer); cryStream.Write(buffer, 0, (int)writeSize); filesize -= writeSize; } cryStream.FlushFinalBlock(); return Spludlow.Hashing.Hex(hash.Hash); } } } } public static string MakeSHA1Giga(string filename, decimal gigabytes) { return MakeSHA1(filename, (ulong)(gigabytes * 1024 * 1024 * 1024)); } public static string MakeSHA1Mega(string filename, decimal megabytes) { return MakeSHA1(filename, (ulong)(megabytes * 1024 * 1024)); } public static string MakeSHA1Kilo(string filename, decimal kilobytes) { return MakeSHA1(filename, (ulong)(kilobytes * 1024)); } /// /// Copy file and keep exclusivly open for specified number of seconds /// public static void CopySlow(string sourceFilename, string targetFilename, int seconds) { using (FileStream readStream = new FileStream(sourceFilename, FileMode.Open)) { using (FileStream writeStream = new FileStream(targetFilename, FileMode.Create, FileAccess.Write, FileShare.None)) { readStream.CopyTo(writeStream); System.Threading.Thread.Sleep(seconds * 1000); } } } } }