//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// MemoryMapper1.cs 15-May-18//\\//\\//\\
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// v4.4.5.53 Mapped in to Lock Out//\\//\\
// v4.4.5.53 Split from PrintForm2\\//\\//
// v4.4.6.54 mm2 & mm3 transition //\\//\\
// Obsoletes mmf2 and mmf3 stuff. \\//\\//
// (c) John P. Edwards 20-May-2018//\\//\\
// v4.5.6.54 name & path/no-path mech/\\//
// Mapped in to Lock Out, extended//\\//\\
// v4.5.7.54neatobeto! All Dialed in!/\\//
// v4.5.7.56nights Brings in Strings!\//\\
// v4.5.7.56nighttime perfects class//\\//
// v4.5.7.56nightvision has Auto-Size!//\\
// v4.5.7.57 Auto-Size & args[6] Delete!//
// v4.5.7.57 Perfects Int64 Handling. Fini
// v4.5.7.58 Polished & Welltested. Jun-28
// v4.5.8.60 Revised For: Int64 lengths.
// v4.5.9.63 Final Integrations. 15-Aug
// v4.6.9.64 26-Aug-2018 Added omitted
// locking on the rest of the methods.oop
// 29-Aug-2018 Clarifies Resource Access:
// v4.6.9.65 Replaced Lock w/ Mutex 4 IPC!
// v4.6.9.67 08-Sep-2018 Mutex Properties.
// v4.8.1.78 06-Oct-2018 LastAccess Time.
// v4.9.3.87 15-Nov-2018 Favorites Mods.
// v4.9.4.89 20-Nov-2018 Ironing & Polish.
// v5.0.6.00 21-Feb-2019 Updated all:
// List<T> to Collection<T>
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading;
using MCR =
MyCustomLibrary.Properties.Resources;
namespace MyCustomLibrary
{
public static partial class MemoryMapper
{
private static readonly Mutex
Mtx1 = new Mutex(false, MCR.M1);
private static readonly Mutex
Mtx2 = new Mutex(false, MCR.M2);
private static readonly Mutex
Mtx3 = new Mutex(false, MCR.M3);
#region Doc
// mmf = Memory Mapped File(s) Arguments
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// args[0] = Full Path to mmf.
// args[1] = Size of file in bytes,
// args[2] = Start @ Byte (offset)
// args[3] = What to write? (OR Shred? T/F)
// args[4] = true; Read?
// args[5] = this mapping's name.
// args[6] = true; Delete after Read?
// args[7] = View Length from Offset.
// (if Given) Not Required, either way.8
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#endregion
#region MemoryMapper Class: Common Code.
private static void Writer(string path)
{
using (new Mutex(false, "Writer"))
{
var time = DateTime.Now;
File.SetLastWriteTime(path, time);
File.SetLastAccessTime(path, time);
}
}
private static void EndGame(
bool del, string path)
{
using (new Mutex(false, "EndGame"))
{
if (del && File.Exists(path))
File.Delete(path);
else if (File.Exists(path))
File.SetLastAccessTime(
path, DateTime.Now);
}
}
#endregion Common Code
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
#region Memory Mapped Files: Read & Write Bytes
// Reads a List of Bytes from mmf.
// v4.5.7.56 04-Jun-2018 for ReUseAbility.
public static Collection<byte>
ReadBytes(object[] args)
{
Mtx1.WaitOne();
const string t = "Read Bytes";
long size, offs, view = 0;
if (args == null || args.Length < 7)
throw new ArgumentException(t);
bool read, dele, shred;
string path, name;
try // now unbox args.
{ path =args[0].ToString();//[0]);
size = Convert.ToInt64(args[1]);
offs = Convert.ToInt64(args[2]);
try { shred =
Convert.ToBoolean( args[3]);}
catch(FormatException){shred=false;}
catch(InvalidCastException){shred=false;}
read=Convert.ToBoolean(args[4]);
name=args[5].ToString(); //[5]);
dele=Convert.ToBoolean(args[6]);
if (args.Length > 7)// args[7]);
{ try { view = Convert.ToInt64(args[7]); }
catch (FormatException) { view = 0; }
catch(InvalidCastException){ view = 0;}}
} catch (InvalidCastException)
{ throw new InvalidCastException(t); }
catch (FormatException)
{ throw new FormatException(t); }
var bites = ReadBytesKernal(path, name,
size, read, offs, view, shred);
EndGame(dele, path);
Mtx1.ReleaseMutex();
return bites;
}
/********************************************
* Self Contained Instance-N ^v Methods: *
* ThreadFileSafe Useable by any instance. *
* so long as the file varies or such.-JpE- *
********************************************/
public static bool WriteBytes(object[] args)
{
Mtx1.WaitOne();
if(args==null||args.Length < 7) throw new
ArgumentException("Write Bytes");
string path,name;long size,offset,view = 0;
try { path = args[0].ToString(); }
catch (FormatException)
{ path = Convert.ToString(args[0]); }
try { size =(Convert.ToInt64(args[1]));}
catch (InvalidCastException){size= 1;}
try { offset =Convert.ToInt64(args[2]);}
catch (FormatException)
{ Mtx1.ReleaseMutex(); return false; }
catch(InvalidCastException)
{ Mtx1.ReleaseMutex(); return false; }
try { name = args[5].ToString(); }
catch(InvalidCastException){name="mmf";}
catch(FormatException) { name = "mmf"; }
if (args.Length > 7)
{ try { view = Convert.ToInt64(args[7]); }
catch (FormatException) { view = 0; }
catch (InvalidCastException) { view = 0L; }
catch(OverflowException) { view = 0; } }
if (!WriteBytesKernal(path, name, size,
offset, view, args[3]))
{ Mtx1.ReleaseMutex();
return false; }
Writer(path);
Mtx1.ReleaseMutex();
return true;
}
#endregion Read/Write Bytes
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
#region Mmf: Int64 Words @ 8 bytes each.
/// <summary> Server-Side Code
/// Generic enough to reuse from
/// either side, just watch for,
/// like, file already open errors.
/// Updated to return Generic List
/// v4.5.7.56 04-May-2018 -JpE-
/// NOTE: args[3] is now a List
/// of Long Integers. Adds Reuseability.
/// v4.6.9.65 29-Aug-2018 Mutex'd
/// </summary>
/// <param name="array"></param>
/// <returns></returns>
public static Collection<long>
ReadInt64(object[] array)
{
Mtx2.WaitOne();
if (array == null || array[2] == null
|| array.Length < 7) throw new
ArgumentException("Read Int64");
string t, h;
long s, o, v = 0L;
bool r, d, b;
var c = new Collection<long>();
try{h =array[0].ToString();//[0]);
s = Convert.ToInt64( array[1]);
o = Convert.ToInt64( array[2]);
try { b =
Convert.ToBoolean( array[3]); }
catch (FormatException) { b = false;}
catch(InvalidCastException){b=false;}
r = Convert.ToBoolean(array[4]);
t = array[5].ToString(); //[5]);
d = Convert.ToBoolean(array[6]);
if (array.Length > 7)
v = Convert.ToInt64(array[7]); }
catch (InvalidCastException)
{ Mtx2.ReleaseMutex(); return c; }
catch (FormatException)
{ Mtx2.ReleaseMutex(); return c; }
c = ReadInt64Kernal(s, h, t, r, o, v, b);
if (!r) { Mtx1.ReleaseMutex();
return c; }
EndGame(d, h);
Mtx2.ReleaseMutex();
return c;
}
/// <summary> Client-Side Code
/// v4.5.6.54nab 20-May-2018
/// Generic enough to reuse from
/// either side, just watch for,
/// like, file already open errors in IO.
/// v4.5.7.54 25-May-2018 Int64 @ 8 bytes ea.
/// v4.5.7.56 04-Jun args[3] is now
/// a List of Int64 = Long values.
/// </summary>
/// <param name="args"></param>
public static bool
WriteInt64(object[] args)
{
Mtx2.WaitOne();
try { if (args == null
|| args[2] == null
|| args.Length < 7
|| !args.Any()) return false; }
catch(ArgumentException){return false;}
const long k = 0L;
const string m = "mm3";
long s, o, v = 0L; string n, h;
try { h = args[0].ToString(); }
catch (FormatException) { h = ""; }
try { s = Convert.ToInt64(args[1]); }
catch (InvalidCastException) { s = k; }
catch (FormatException) { s = k; }
try { o = Convert.ToInt64(args[2]); }
catch (InvalidCastException){ o = 0L; }
catch (FormatException) { o = 0L; }
try { n = args[5].ToString(); }
catch (FormatException) { n = m; }
catch (InvalidCastException) { n = m; }
if (args.Length > 7)
{ try { v = Convert.ToInt64(args[7]); }
catch (FormatException) { v = 0; }
catch (InvalidCastException){v = 0;}
catch (OverflowException){v = 0; } }
if (!WriteLongKernal(
args[3], s, h, n, o, v))
{ Mtx2.ReleaseMutex();
return false; }
Writer(h);
Mtx2.ReleaseMutex();
return true;
}
#endregion Mmf: Int64 Words @ 8 bytes each.
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
#region Read/Write Strings
/// <summary> Read in List of strings.
/// -JpE- v4.5.7.56 01-Jun-18 (from Mmf ^)
/// SEE DOC ABOVE FOR REQUIRED ARG VALUES.
/// Returns a List of string references.
/// If size arg is 0, it calculates j.i.t.
/// args[6], the 7th element now contains
/// a bool for delete file when finished. T/F
/// v4.9.3.86 Added the 8th element:
/// View Length. November 11th, 2018 -JpE-
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public static Collection<string>
ReadStrings(object[] args)
{
Mtx3.WaitOne();
if (args == null || args.Length < 7
|| string.IsNullOrEmpty(
args[0].ToString()))
{ Mtx3.ReleaseMutex(); return null; }
string path, name;
long size, offs, view = 0L;
bool read, del, shred = false;
try{path = args[0].ToString();//0]);
size = Convert.ToInt64(args[1]);
offs = Convert.ToInt64(args[2]);
// Only used for Writes args[3]); BUT...
read = Convert.ToBoolean(args[4]);
name = args[5].ToString(); //[5]);
del = Convert.ToBoolean(args[6]);
if (args.Length > 7)
view = Convert.ToInt64(args[7]);
try // v Reused here as a Special Case.
{ if (args[3] != null) shred =
Convert.ToBoolean(args[3]); }
catch (FormatException) { shred=false; }
catch(InvalidCastException){shred=false;}}
catch (ArgumentException)
{ Mtx3.ReleaseMutex(); return null; }
catch (InvalidCastException)
{ Mtx3.ReleaseMutex(); return null; }
if (!File.Exists(path))
{ Mtx3.ReleaseMutex(); return null; }
var input = ReadStringsKernal(
path, size, offs, name, read, view, shred);
if (input == null || !read )
{ Mtx3.ReleaseMutex();
return null; }
EndGame(del, path);
Mtx3.ReleaseMutex();
return input;
}
/// <summary> Write List of strings
/// to memory mapped file (args[0]).
/// Return true only if EVERYTHING went ok.
/// REM: args[3] is a List of Strings!
/// Strings to write as UNICODE encoded bytes.
/// SEE DOC ABOVE FOR REQUIRED ARG VALUES.
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public static bool WriteStrings(object[] args)
{
if (args == null
|| args.Length < 7) return false;
Mtx3.WaitOne();
Collection<string> strings;
try { strings = args[3] as Collection<string>; }
catch(ArgumentException)
{ Mtx3.ReleaseMutex(); return false; }
catch(InvalidCastException)
{ Mtx3.ReleaseMutex(); return false; }
if ( strings == null || strings.Count < 1
|| string.IsNullOrEmpty(args[0].ToString()))
{ Mtx3.ReleaseMutex(); return false; }
string file, name; long size, offs, view = 0L;
try// REM: args[4] doesn't apply to writes.
{ file = args[0].ToString();//[0]);
size = Convert.ToInt64( args[1]);
offs = Convert.ToInt64( args[2]);
name = args[5].ToString(); //5]);
if (args.Length > 7)
view = Convert.ToInt64(args[7]); }
catch (ArgumentException)
{ Mtx3.ReleaseMutex(); return false; }
catch (InvalidCastException)
{ Mtx3.ReleaseMutex(); return false; }
if (size == 0) size = offs + CalcSize(strings);
// This Call to CalcSize is ^ for AutoSize! 0
var is1 = WriteStringsKernal(file,
name, size, offs, view, strings);
if (is1) Writer(file);
Mtx3.ReleaseMutex();
return is1;
}
private static long CalcSize(
ICollection<string> strings)
{
if (strings == null || strings.Count < 1)
throw new ArgumentException("CalcSize");
long size; try
{ size = strings.Sum(s => s.Length);
size = (size* 2) + (2* strings.Count); }
catch(ArgumentNullException){size = 256; }
catch (OverflowException) { size = 256; }
// =-> w/Int16 UniCode it's 2 bytes per char.
return size;// 2 x 8 ^
// NOTE: So 2x Chars + 2 ea. <-= <-=
}// <-= EOM <-= for ^ int16 ^ lengths.
//=-> =-> =-> (Length stored before ea string.)
#endregion Read/Write Strings
//\\//\\//\\//\\//\\//\\//\\//\\//\\// EOC
}
}
Comments