Mega Code Archive

 
Categories / C# / File Stream
 

ReadWrite File Transacted

/*== == Copyright : BlueCurve (c) == Licence   : Gnu/GPL v2.x == Author    : Teddy Albina == Email     : bluecurveteam@gmail.com == Web site  : http://www.codeplex.com/BlueCurve */ using System; using System.IO; using System.Text; using System.Transactions; using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices; using System.Runtime.Serialization.Formatters.Binary; namespace BlueCurve.Search.Common.IO {     /// <summary>     /// Fournit des méthodes de gestions du système de fichier     /// </summary>     public class CommonStream     {         #region Import native methods         /// <summary>         /// Méthode native vérifiant si un répertoire est vide         /// </summary>         /// <param name="pszPath">Chemin du répertoire à tester</param>         /// <returns>bool</returns>         [DllImport("shlwapi.dll", CharSet = CharSet.Auto)]         private extern static bool PathIsDirectoryEmpty(string pszPath);         #region 'Kernel transaction manager api management'         /// <summary>         /// Represente un handle de transaction         /// </summary>         public sealed class SafeTransactionHandle : SafeHandleZeroOrMinusOneIsInvalid         {             private SafeTransactionHandle()                 : base(true)             {             }             public SafeTransactionHandle(IntPtr preexistingHandle, bool ownsHandle)                 : base(ownsHandle)             {                 SetHandle(preexistingHandle);             }             public enum FileAccess             {                 GENERIC_READ = unchecked((int)0x80000000),                 GENERIC_WRITE = 0x40000000             }             [Flags]             public enum FileShare             {                 FILE_SHARE_NONE = 0x00,                 FILE_SHARE_READ = 0x01,                 FILE_SHARE_WRITE = 0x02,                 FILE_SHARE_DELETE = 0x04             }             public enum FileMode             {                 CREATE_NEW = 1,                 CREATE_ALWAYS = 2,                 OPEN_EXISTING = 3,                 OPEN_ALWAYS = 4,                 TRUNCATE_EXISTING = 5             }             [DllImport("Kernel32.dll", SetLastError = true)]             private static extern bool CloseHandle(IntPtr handle);             override protected bool ReleaseHandle()             {                 return CloseHandle(handle);             }         }         /// <summary>         /// Importation de la fonction native CreateFileTransacted() permettant         /// de créer une transaction ntfs         /// </summary>         /// <returns>SafeFileHandle</returns>         [DllImport("Kernel32.Dll", EntryPoint = "CreateFileTransacted", CharSet = CharSet.Unicode, SetLastError = true)]         protected static extern SafeFileHandle CreateFileTransacted(                [In] String lpFileName,                [In] SafeTransactionHandle.FileAccess dwDesiredAccess,                [In] SafeTransactionHandle.FileShare dwShareMode,                [In] IntPtr lpSecurityAttributes,                [In] SafeTransactionHandle.FileMode dwCreationDisposition,                [In] int dwFlagsAndAttributes,                [In] IntPtr hTemplateFile,                [In] SafeTransactionHandle txHandle,                [In] IntPtr miniVersion,                [In] IntPtr extendedOpenInformation            );         /// <summary>         /// Importation de l'interface KTM         /// </summary>         [ComImport]         [Guid("79427A2B-F895-40e0-BE79-B57DC82ED231")]         [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]         protected interface IKernelTransaction         {             void GetHandle(out SafeTransactionHandle ktmHandle);         }         #endregion         #endregion         /// <summary>         /// Copie un stream dans un autre         /// de façon asynchrone         /// http://msdn.microsoft.com/fr-fr/magazine/cc337900.aspx         /// </summary>         /// <param name="source">Stream source</param>         /// <param name="destination">Stream destination</param>         /// <param name="completed">Action()</param>         public static void CopyStreamToStream(FileStream source, FileStream destination,                                               Action<FileStream, FileStream, Exception> completed)         {             byte[] buffer = new byte[0x1024];             System.ComponentModel.AsyncOperation asyncOp = System.ComponentModel.AsyncOperationManager.CreateOperation(null);                        Action<Exception> done = e =>             {                 if (completed != null) asyncOp.Post(delegate                 {                     completed(source, destination, e);                 }, null);             };             AsyncCallback rc = null;             rc = readResult =>             {                 try                 {                     int read = source.EndRead(readResult);                     if (read > 0)                     {                         destination.BeginWrite(buffer, 0, read, writeResult =>                         {                             try                             {                                 destination.EndWrite(writeResult);                                 source.BeginRead(                                     buffer, 0, buffer.Length, rc, null);                             }                             catch (Exception exc) { done(exc); }                         }, null);                     }                     else done(null);                 }                 catch (Exception exc) { done(exc); }             };             source.BeginRead(buffer, 0, buffer.Length, rc, null);         }         /// <summary>         /// Vérifie qu'un répertoire est vide         /// </summary>         /// <param name="path">Chemin de fichier du répertoire</param>         /// <returns>bool</returns>         public static bool DirectoryIsEmpty(string path)         {             return PathIsDirectoryEmpty(path);         }         #region Transactional methods         /// <summary>         /// Ecrit un fichier de façon transactionnel         /// </summary>         /// <param name="data">Données à écrire</param>         /// <param name="path">Chemin du fichier dans lequel écrire les données</param>         /// <returns>Statut de l'opération</returns>         public static bool WriteFileTransacted(object data, string path)         {             if (data == null)                 return false;             SafeTransactionHandle txHandle = null;             SafeFileHandle fileHandle = null;             bool response = true;             try             {                 IKernelTransaction kernelTx = (IKernelTransaction)TransactionInterop.GetDtcTransaction(System.Transactions.Transaction.Current);                 kernelTx.GetHandle(out txHandle);                 fileHandle                     = CreateFileTransacted(                         path                         , SafeTransactionHandle.FileAccess.GENERIC_WRITE                         , SafeTransactionHandle.FileShare.FILE_SHARE_NONE                         , IntPtr.Zero                         , SafeTransactionHandle.FileMode.CREATE_ALWAYS                         , 0                         , IntPtr.Zero                         , txHandle                         , IntPtr.Zero                         , IntPtr.Zero);                 if (fileHandle.IsInvalid)                     throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());                 using (FileStream stream = new FileStream(fileHandle, FileAccess.Write, 1024, false))                 {                     BinaryFormatter writer = new BinaryFormatter();                     writer.Serialize(stream, data);                     stream.Close();                 }             }             catch             {                 System.Transactions.Transaction.Current.Rollback();                 response = false;             }             finally             {                 if (fileHandle != null && !fileHandle.IsInvalid)                 {                     fileHandle.Close();                     fileHandle.Dispose();                 }                 if (txHandle != null && !txHandle.IsInvalid)                 {                     txHandle.Close();                     txHandle.Dispose();                 }             }             return response;         }         /// <summary>         /// Lit un fichier de façon transactionnel         /// </summary>         /// <param name="path">Chemin du fichier à lire</param>         /// <returns>Données lu</returns>         public object ReadFileTransacted(string path)         {             if (!File.Exists(path))                 return null;             SafeTransactionHandle txHandle = null;             SafeFileHandle fileHandle = null;             object raw = null;             try             {                 IKernelTransaction kernelTx = (IKernelTransaction)TransactionInterop.GetDtcTransaction(System.Transactions.Transaction.Current);                 kernelTx.GetHandle(out txHandle);                 fileHandle                     = CreateFileTransacted(                         path                         , SafeTransactionHandle.FileAccess.GENERIC_READ                         , SafeTransactionHandle.FileShare.FILE_SHARE_READ                         , IntPtr.Zero                         , SafeTransactionHandle.FileMode.OPEN_ALWAYS                         , 0                         , IntPtr.Zero                         , txHandle                         , IntPtr.Zero                         , IntPtr.Zero);                 if (fileHandle.IsInvalid)                     throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());                 using (FileStream stream = new FileStream(fileHandle, FileAccess.Read, 1024, false))                 {                     BinaryFormatter reader = new BinaryFormatter();                     raw = reader.Deserialize(stream);                 }             }             catch             {                 raw = null;             }             finally             {                 if (fileHandle != null && !fileHandle.IsInvalid)                 {                     fileHandle.Close();                     fileHandle.Dispose();                 }                 if (txHandle != null && !txHandle.IsInvalid)                 {                     txHandle.Close();                     txHandle.Dispose();                 }             }             return raw;         }         #endregion     } }