- exclude translation helper from build
a5b4538e
Dimitar Tsenev
committed
1 changed file
BExplorer.sln
/BExplorer.sln-375
/BExplorer.sln
Add comment 1 Minus  //
Add comment 2 Minus  // AsyncUnbuffCopy.cs
Add comment 3 Minus  //
Add comment 4 Minus  // Authors:
Add comment 5 Minus  // Wesley D. Brown <wes@planetarydb.com>
Add comment 6 Minus  //
Add comment 7 Minus  // Copyright (C) 2010 SQLServerIO (http://www.SQLServerIO.com)
Add comment 8 Minus  //
Add comment 9 Minus  // Permission is hereby granted, free of charge, to any person obtaining
Add comment 10 Minus  // a copy of this software and associated documentation files (the
Add comment 11 Minus  // "Software"), to deal in the Software without restriction, including
Add comment 12 Minus  // without limitation the rights to use, copy, modify, merge, publish,
Add comment 13 Minus  // distribute, sublicense, and/or sell copies of the Software, and to
Add comment 14 Minus  // permit persons to whom the Software is furnished to do so, subject to
Add comment 15 Minus  // the following conditions:
Add comment 16 Minus  //
Add comment 17 Minus  // The above copyright notice and this permission notice shall be
Add comment 18 Minus  // included in all copies or substantial portions of the Software.
Add comment 19 Minus  //
Add comment 20 Minus  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Add comment 21 Minus  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Add comment 22 Minus  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Add comment 23 Minus  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
Add comment 24 Minus  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
Add comment 25 Minus  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
Add comment 26 Minus  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Add comment 27 Minus  //
Add comment 28 Minus  
Add comment 29 Minus  using System;
Add comment 30 Minus  using System.IO;
Add comment 31 Minus  using System.Runtime.CompilerServices;
Add comment 32 Minus  using System.Security.Cryptography;
Add comment 33 Minus  using System.Text;
Add comment 34 Minus  using System.Threading;
Add comment 35 Minus  
Add comment 36 Minus  namespace BExplorer.Shell {
Add comment 37 Minus   public class CopyEventArgs {
Add comment 38 Minus   public String InFileName { get; set; }
Add comment 39 Minus   public String OutFileName { get; set; }
Add comment 40 Minus   public long BytesTransferred { get; set; }
Add comment 41 Minus   public long TotalBytes { get; set; }
Add comment 42 Minus   }
Add comment 43 Minus   public class AsyncUnbuffCopy {
Add comment 44 Minus  
Add comment 45 Minus   public event EventHandler<CopyEventArgs> OnProgress;
Add comment 46 Minus  
Add comment 47 Minus   //file names
Add comment 48 Minus   private static string _inputfile;
Add comment 49 Minus   private static string _outputfile;
Add comment 50 Minus  
Add comment 51 Minus   //checksum holders
Add comment 52 Minus   private static string _infilechecksum;
Add comment 53 Minus   private static string _outfilechecksum;
Add comment 54 Minus  
Add comment 55 Minus   //show write progress
Add comment 56 Minus   private static bool _reportprogress;
Add comment 57 Minus  
Add comment 58 Minus   //cursor position
Add comment 59 Minus   private static int _origRow;
Add comment 60 Minus   private static int _origCol;
Add comment 61 Minus  
Add comment 62 Minus   //number of chunks to copy
Add comment 63 Minus   private static int _numchunks;
Add comment 64 Minus  
Add comment 65 Minus   //track read state and read failed state
Add comment 66 Minus   private static bool _readfailed;
Add comment 67 Minus  
Add comment 68 Minus   //syncronization object
Add comment 69 Minus   private static readonly object Locker1 = new object();
Add comment 70 Minus  
Add comment 71 Minus   //buffer size
Add comment 72 Minus   public static int CopyBufferSize;
Add comment 73 Minus   private static long _infilesize;
Add comment 74 Minus  
Add comment 75 Minus   //buffer read
Add comment 76 Minus   public static byte[] Buffer1;
Add comment 77 Minus   private static int _bytesRead1;
Add comment 78 Minus  
Add comment 79 Minus   //buffer overlap
Add comment 80 Minus   public static byte[] Buffer2;
Add comment 81 Minus   private static bool _buffer2Dirty;
Add comment 82 Minus   private static int _bytesRead2;
Add comment 83 Minus  
Add comment 84 Minus   //buffer write
Add comment 85 Minus   public static byte[] Buffer3;
Add comment 86 Minus  
Add comment 87 Minus   //total bytes read
Add comment 88 Minus   private static long _totalbytesread;
Add comment 89 Minus   private static long _totalbyteswritten;
Add comment 90 Minus  
Add comment 91 Minus   //filestreams
Add comment 92 Minus   private static FileStream _infile;
Add comment 93 Minus   private static FileStream _outfile;
Add comment 94 Minus  
Add comment 95 Minus   //secret sauce for unbuffered IO
Add comment 96 Minus   const FileOptions FileFlagNoBuffering = (FileOptions)0x20000000;
Add comment 97 Minus  
Add comment 98 Minus   private static void AsyncReadFile() {
Add comment 99 Minus   //open input file
Add comment 100 Minus   try {
Add comment 101 Minus   _infile = new FileStream(_inputfile, FileMode.Open, FileAccess.Read, FileShare.Read, CopyBufferSize, FileFlagNoBuffering);
Add comment 102 Minus   } catch {
Add comment 103 Minus   throw;
Add comment 104 Minus   }
Add comment 105 Minus   //if we have data read it
Add comment 106 Minus   while (_totalbytesread < _infilesize) {
Add comment 107 Minus  
Add comment 108 Minus   _bytesRead1 = _infile.Read(Buffer1, 0, CopyBufferSize);
Add comment 109 Minus   Monitor.Enter(Locker1);
Add comment 110 Minus   try {
Add comment 111 Minus   while (_buffer2Dirty) Monitor.Wait(Locker1);
Add comment 112 Minus   Buffer.BlockCopy(Buffer1, 0, Buffer2, 0, _bytesRead1);
Add comment 113 Minus   _buffer2Dirty = true;
Add comment 114 Minus   _bytesRead2 = _bytesRead1;
Add comment 115 Minus   _totalbytesread = _totalbytesread + _bytesRead1;
Add comment 116 Minus   Monitor.PulseAll(Locker1);
Add comment 117 Minus  
Add comment 118 Minus   } catch {
Add comment 119 Minus   _readfailed = true;
Add comment 120 Minus   throw;
Add comment 121 Minus   } finally { Monitor.Exit(Locker1); }
Add comment 122 Minus   }
Add comment 123 Minus   //clean up open handle
Add comment 124 Minus   _infile.Close();
Add comment 125 Minus   _infile.Dispose();
Add comment 126 Minus   }
Add comment 127 Minus  
Add comment 128 Minus   private void AsyncWriteFile() {
Add comment 129 Minus   //open output file set length to prevent growth and file fragmentation and close it.
Add comment 130 Minus   //We do this to prevent file fragmentation and make the write as fast as possible.
Add comment 131 Minus   try {
Add comment 132 Minus   _outfile = new FileStream(_outputfile, FileMode.Create, FileAccess.Write, FileShare.None, 8, FileOptions.WriteThrough);
Add comment 133 Minus  
Add comment 134 Minus   //set file size to minimum of one buffer to cut down on fragmentation
Add comment 135 Minus   _outfile.SetLength(_infilesize > CopyBufferSize ? _infilesize : CopyBufferSize);
Add comment 136 Minus  
Add comment 137 Minus   _outfile.Close();
Add comment 138 Minus   _outfile.Dispose();
Add comment 139 Minus   } catch {
Add comment 140 Minus   throw;
Add comment 141 Minus   }
Add comment 142 Minus  
Add comment 143 Minus   //open file for write unbuffered
Add comment 144 Minus   try {
Add comment 145 Minus   _outfile = new FileStream(_outputfile, FileMode.Open, FileAccess.Write, FileShare.None, 8, FileOptions.WriteThrough | FileFlagNoBuffering);
Add comment 146 Minus  
Add comment 147 Minus   } catch {
Add comment 148 Minus   throw;
Add comment 149 Minus   }
Add comment 150 Minus  
Add comment 151 Minus   var pctinc = 0.0;
Add comment 152 Minus   var progress = pctinc;
Add comment 153 Minus  
Add comment 154 Minus   //progress stuff
Add comment 155 Minus   if (_reportprogress) {
Add comment 156 Minus  
Add comment 157 Minus   pctinc = 100.00 / _numchunks;
Add comment 158 Minus   }
Add comment 159 Minus  
Add comment 160 Minus   while ((_totalbyteswritten < _infilesize) && !_readfailed) {
Add comment 161 Minus   lock (Locker1) {
Add comment 162 Minus  
Add comment 163 Minus   while (!_buffer2Dirty) Monitor.Wait(Locker1);
Add comment 164 Minus  
Add comment 165 Minus   Buffer.BlockCopy(Buffer2, 0, Buffer3, 0, _bytesRead2);
Add comment 166 Minus   _buffer2Dirty = false;
Add comment 167 Minus  
Add comment 168 Minus   _totalbyteswritten = _totalbyteswritten + CopyBufferSize;
Add comment 169 Minus  
Add comment 170 Minus   Monitor.PulseAll(Locker1);
Add comment 171 Minus   //fancy dan in place percent update on each write.
Add comment 172 Minus   if (this.OnProgress != null) {
Add comment 173 Minus   this.OnProgress.Invoke(this, new CopyEventArgs() {
Add comment 174 Minus   InFileName = _inputfile,
Add comment 175 Minus   OutFileName = _outputfile,
Add comment 176 Minus   BytesTransferred = _totalbyteswritten,
Add comment 177 Minus   TotalBytes = _infilesize
Add comment 178 Minus   });
Add comment 179 Minus   }
Add comment 180 Minus   if (_reportprogress) {
Add comment 181 Minus  
Add comment 182 Minus   Console.SetCursorPosition(_origCol, _origRow);
Add comment 183 Minus   if (progress < 101 - pctinc) {
Add comment 184 Minus   progress = progress + pctinc;
Add comment 185 Minus   Console.Write("%{0}", Math.Round(progress, 0));
Add comment 186 Minus   }
Add comment 187 Minus   }
Add comment 188 Minus   }
Add comment 189 Minus   try {
Add comment 190 Minus   _outfile.Write(Buffer3, 0, CopyBufferSize);
Add comment 191 Minus   } catch {
Add comment 192 Minus   throw;
Add comment 193 Minus   }
Add comment 194 Minus   }
Add comment 195 Minus  
Add comment 196 Minus   //close the file handle that was using unbuffered and write through
Add comment 197 Minus  
Add comment 198 Minus   _outfile.Close();
Add comment 199 Minus   _outfile.Dispose();
Add comment 200 Minus  
Add comment 201 Minus   try {
Add comment 202 Minus  
Add comment 203 Minus   _outfile = new FileStream(_outputfile, FileMode.Open, FileAccess.Write, FileShare.None, 8,
Add comment 204 Minus   FileOptions.WriteThrough);
Add comment 205 Minus   _outfile.SetLength(_infilesize);
Add comment 206 Minus   _outfile.Close();
Add comment 207 Minus   _outfile.Dispose();
Add comment 208 Minus   } catch {
Add comment 209 Minus   throw;
Add comment 210 Minus   }
Add comment 211 Minus   }
Add comment 212 Minus  
Add comment 213 Minus   public int AsyncCopyFileUnbuffered(string inputfile, string outputfile, bool overwrite,bool movefile, bool checksum, int buffersize, bool reportprogress) {
Add comment 214 Minus  
Add comment 215 Minus   //report write progress
Add comment 216 Minus   _reportprogress = reportprogress;
Add comment 217 Minus  
Add comment 218 Minus   //set file name globals
Add comment 219 Minus   _inputfile = inputfile;
Add comment 220 Minus   _outputfile = outputfile;
Add comment 221 Minus  
Add comment 222 Minus   //setup single buffer size, remember this will be x3.
Add comment 223 Minus   CopyBufferSize = buffersize * 1024 * 1024;
Add comment 224 Minus  
Add comment 225 Minus   //buffer read
Add comment 226 Minus   Buffer1 = new byte[CopyBufferSize];
Add comment 227 Minus  
Add comment 228 Minus   //buffer overlap
Add comment 229 Minus   Buffer2 = new byte[CopyBufferSize];
Add comment 230 Minus  
Add comment 231 Minus   //buffer write
Add comment 232 Minus   Buffer3 = new byte[CopyBufferSize];
Add comment 233 Minus  
Add comment 234 Minus   //clear all flags and handles
Add comment 235 Minus   _totalbytesread = 0;
Add comment 236 Minus   _totalbyteswritten = 0;
Add comment 237 Minus   _bytesRead1 = 0;
Add comment 238 Minus   _buffer2Dirty = false;
Add comment 239 Minus  
Add comment 240 Minus   //if the overwrite flag is set to false check to see if the file is there.
Add comment 241 Minus   if (File.Exists(outputfile) && !overwrite) {
Add comment 242 Minus  
Add comment 243 Minus   Console.WriteLine("Destination File Exists!");
Add comment 244 Minus   return 0;
Add comment 245 Minus   }
Add comment 246 Minus  
Add comment 247 Minus   //create the directory if it doesn't exist
Add comment 248 Minus   if (!Directory.Exists(outputfile)) {
Add comment 249 Minus   try {
Add comment 250 Minus   // ReSharper disable AssignNullToNotNullAttribute
Add comment 251 Minus   Directory.CreateDirectory(Path.GetDirectoryName(outputfile));
Add comment 252 Minus   // ReSharper restore AssignNullToNotNullAttribute
Add comment 253 Minus   } catch (Exception e) {
Add comment 254 Minus  
Add comment 255 Minus   Console.WriteLine("Create Directory Failed.");
Add comment 256 Minus   Console.WriteLine(e.Message);
Add comment 257 Minus   throw;
Add comment 258 Minus   }
Add comment 259 Minus   }
Add comment 260 Minus  
Add comment 261 Minus   //get input file size for later use
Add comment 262 Minus   var inputFileInfo = new FileInfo(_inputfile);
Add comment 263 Minus   _infilesize = inputFileInfo.Length;
Add comment 264 Minus  
Add comment 265 Minus   //get number of buffer sized chunks used to correctly display percent complete.
Add comment 266 Minus   _numchunks = (int)((_infilesize / CopyBufferSize) <= 0 ? (_infilesize / CopyBufferSize) : 1);
Add comment 267 Minus  
Add comment 268 Minus  
Add comment 269 Minus   Console.WriteLine("File Copy Started");
Add comment 270 Minus  
Add comment 271 Minus   //create read thread and start it.
Add comment 272 Minus   var readfile = new Thread(AsyncReadFile) { Name = "ReadThread", IsBackground = true };
Add comment 273 Minus   readfile.Start();
Add comment 274 Minus  
Add comment 275 Minus  
Add comment 276 Minus   //create write thread and start it.
Add comment 277 Minus   var writefile = new Thread(AsyncWriteFile) { Name = "WriteThread", IsBackground = true };
Add comment 278 Minus   writefile.Start();
Add comment 279 Minus  
Add comment 280 Minus   if (_reportprogress) {
Add comment 281 Minus   //set fancy curor position
Add comment 282 Minus   _origRow = Console.CursorTop;
Add comment 283 Minus   _origCol = Console.CursorLeft;
Add comment 284 Minus   }
Add comment 285 Minus  
Add comment 286 Minus   //wait for threads to finish
Add comment 287 Minus   readfile.Join();
Add comment 288 Minus   writefile.Join();
Add comment 289 Minus  
Add comment 290 Minus   //leave a blank line for the progress indicator
Add comment 291 Minus   if (_reportprogress)
Add comment 292 Minus   Console.WriteLine();
Add comment 293 Minus  
Add comment 294 Minus  
Add comment 295 Minus  
Add comment 296 Minus   Console.WriteLine("File Copy Done");
Add comment 297 Minus  
Add comment 298 Minus   if (checksum) {
Add comment 299 Minus  
Add comment 300 Minus   Console.WriteLine("Checksum Source File Started");
Add comment 301 Minus   //create checksum read file thread and start it.
Add comment 302 Minus   var checksumreadfile = new Thread(GetMD5HashFromInputFile) {
Add comment 303 Minus   Name = "checksumreadfile",
Add comment 304 Minus   IsBackground = true
Add comment 305 Minus   };
Add comment 306 Minus   checksumreadfile.Start();
Add comment 307 Minus  
Add comment 308 Minus  
Add comment 309 Minus   Console.WriteLine("Checksum Destination File Started");
Add comment 310 Minus   //create checksum write file thread and start it.
Add comment 311 Minus   var checksumwritefile = new Thread(GetMD5HashFromOutputFile) {
Add comment 312 Minus   Name = "checksumwritefile",
Add comment 313 Minus   IsBackground = true
Add comment 314 Minus   };
Add comment 315 Minus   checksumwritefile.Start();
Add comment 316 Minus  
Add comment 317 Minus   //hang out until the checksums are done.
Add comment 318 Minus   checksumreadfile.Join();
Add comment 319 Minus   checksumwritefile.Join();
Add comment 320 Minus  
Add comment 321 Minus   if (_infilechecksum.Equals(_outfilechecksum)) {
Add comment 322 Minus  
Add comment 323 Minus   Console.WriteLine("Checksum Verified");
Add comment 324 Minus   } else {
Add comment 325 Minus  
Add comment 326 Minus   Console.WriteLine("Checksum Failed");
Add comment 327 Minus   Console.WriteLine("Input File Checksum : {0}", _infilechecksum);
Add comment 328 Minus   Console.WriteLine("Output File Checksum: {0}", _outfilechecksum);
Add comment 329 Minus   }
Add comment 330 Minus   }
Add comment 331 Minus  
Add comment 332 Minus   if (movefile && File.Exists(inputfile) && File.Exists(outputfile))
Add comment 333 Minus   try {
Add comment 334 Minus   File.Delete(inputfile);
Add comment 335 Minus   } catch (IOException ioex) {
Add comment 336 Minus  
Add comment 337 Minus   Console.WriteLine("File in use or locked");
Add comment 338 Minus   Console.WriteLine(ioex.Message);
Add comment 339 Minus   } catch (Exception ex) {
Add comment 340 Minus  
Add comment 341 Minus   Console.WriteLine("File Failed to Delete");
Add comment 342 Minus   Console.WriteLine(ex.Message);
Add comment 343 Minus   }
Add comment 344 Minus   return 1;
Add comment 345 Minus   }
Add comment 346 Minus  
Add comment 347 Minus   //hash input file
Add comment 348 Minus   public void GetMD5HashFromInputFile() {
Add comment 349 Minus   var fs = new FileStream(_inputfile, FileMode.Open, FileAccess.Read, FileShare.None, CopyBufferSize);
Add comment 350 Minus   MD5 md5 = new MD5CryptoServiceProvider();
Add comment 351 Minus   byte[] retVal = md5.ComputeHash(fs);
Add comment 352 Minus   fs.Close();
Add comment 353 Minus  
Add comment 354 Minus   var sb = new StringBuilder();
Add comment 355 Minus   for (var i = 0; i < retVal.Length; i++) {
Add comment 356 Minus   sb.Append(retVal[i].ToString("x2"));
Add comment 357 Minus   }
Add comment 358 Minus   _infilechecksum = sb.ToString();
Add comment 359 Minus   }
Add comment 360 Minus  
Add comment 361 Minus   //hash output file
Add comment 362 Minus   public void GetMD5HashFromOutputFile() {
Add comment 363 Minus   var fs = new FileStream(_outputfile, FileMode.Open, FileAccess.Read, FileShare.None, CopyBufferSize);
Add comment 364 Minus   MD5 md5 = new MD5CryptoServiceProvider();
Add comment 365 Minus   byte[] retVal = md5.ComputeHash(fs);
Add comment 366 Minus   fs.Close();
Add comment 367 Minus  
Add comment 368 Minus   var sb = new StringBuilder();
Add comment 369 Minus   for (var i = 0; i < retVal.Length; i++) {
Add comment 370 Minus   sb.Append(retVal[i].ToString("x2"));
Add comment 371 Minus   }
Add comment 372 Minus   _outfilechecksum = sb.ToString();
Add comment 373 Minus   }
Add comment 374 Minus   }
Add comment 375 Minus  }