/// <summary> /// Instantiates MmfBufferedWriter. /// </summary> /// <param name="ipcType">Identifies memory mapped file and used to authenticate outgoing messages.</param> /// <param name="bufferLength">Length of data segment</param> /// <param name="ignoreExceptions">True if exceptions should be handled; false if they should be returned to the caller.</param> public MmfBufferedWriter(string ipcType, int bufferLength, Niawa.Utilities.UtilsServiceBus utilsBus, bool ignoreExceptions) { try { _sendQueue = new Queue<NiawaMmfContainer>(); _header = new NiawaMmfBufferHeader(); _ipcType = ipcType; _description = "MmfWriter " + _ipcType; _bufferLength = bufferLength; _ignoreExceptions = ignoreExceptions; //initialize serial ID generator id = utilsBus.InitializeSerialId(Niawa.Utilities.IdGeneratorUtils.ID_ROOT_NIAWA_MMF_CONTAINER); //get random starting message ID Random rnd = new Random(); int startingMsgID = rnd.Next(0, 100000); _msgID = startingMsgID; _threadStatus = new Niawa.Threading.ThreadStatus(_description, 60, utilsBus.InitializeSerialId(Niawa.Utilities.IdGeneratorUtils.ID_ROOT_NIAWA_THREAD_ID).ToString(), string.Empty, null); //thread status _threadStatus.Status = Niawa.Threading.ThreadStatus.STATUS_INITIALIZED; } catch (Exception ex) { logger.Error("[" + _description + "-M] Exception while instantiating: " + ex.Message, ex); if (!ignoreExceptions) throw ex; } }
/// <summary> /// Initialize the buffer header file with empty values /// </summary> private void InitializeHeader() { try { //create a new buffer header _header = new NiawaMmfBufferHeader(); SortedList<int, KeyValuePair<string, DateTime>> entries = new SortedList<int, KeyValuePair<string, DateTime>>(); //populate the buffer header with blank values int ix = 1; while (ix <= 100) { entries.Add(ix, new KeyValuePair<string, DateTime>(string.Empty, new DateTime(1900, 1, 1))); ix++; } _header.Entries = entries; _header.LatestUpdateDate = new DateTime(1900, 1, 1); _header.LatestEntryID = 0; //convert buffer header to bytes byte[] buffer = _header.ToByteArray(); //locked section using (new Niawa.Utilities.SingleGlobalInstance(1000, _ipcType + "_header")) //1000ms timeout on global lock { int msgLength = buffer.Length; int msgID = 0; //open mmf MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen(_ipcType + "_header", _bufferLength); MemoryMappedViewAccessor accessor1Len = mmf.CreateViewAccessor(0, 4); MemoryMappedViewAccessor accessor2ID = mmf.CreateViewAccessor(8, 4); MemoryMappedViewAccessor accessor3Data = mmf.CreateViewAccessor(16, msgLength); //write data accessor1Len.Write<Int32>(0, ref msgLength); accessor2ID.Write<Int32>(0, ref msgID); accessor3Data.WriteArray<byte>(0, buffer, 0, msgLength); } //end locked section } catch (Exception ex) { logger.Error("[" + _description + "-M] Exception while initializing buffer header: " + ex.Message, ex); if (!_ignoreExceptions) throw ex; } }
private NiawaMmfBufferHeader InitializeCachedHeader(NiawaMmfBufferHeader cachedHeader) { try { //create a new buffer header cachedHeader = new NiawaMmfBufferHeader(); SortedList<int, KeyValuePair<string, DateTime>> entries = new SortedList<int, KeyValuePair<string, DateTime>>(); //populate the buffer header with blank values int ix = 1; while (ix <= 100) { entries.Add(ix, new KeyValuePair<string, DateTime>(string.Empty, new DateTime(1900, 1, 1))); ix++; } cachedHeader.Entries = entries; cachedHeader.LatestUpdateDate = new DateTime(1900, 1, 1); cachedHeader.LatestEntryID = 0; return cachedHeader; } catch (Exception ex) { logger.Error("[" + _description + "-M] Exception while initializing buffer header: " + ex.Message, ex); if (!_ignoreExceptions) throw ex; return null; } }
/// <summary> /// Reads data from Mmf Header file into cached header object /// </summary> private bool ReadFromMmfHeaderFile() { /* Memory Mapped File: * accessor1Len: bytes 0-4 total length of file * accessor2ID: bytes 8-12 ID number of message * accessor3Data: variable bytes payload * */ int msgLength; int msgID; MemoryMappedFile mmf; //System.Diagnostics.Debug.WriteLine("MmfBufferedReader [Header]: Filename " + _ipcType + "_header"); try { //open mmf mmf = MemoryMappedFile.OpenExisting(_ipcType + "_header"); } catch (System.IO.FileNotFoundException ex) { System.Diagnostics.Debug.WriteLine("MmfBufferedReader [" + _ipcType + "][Header]: Header file was not found"); throw ex; } MemoryMappedViewAccessor accessor1Len = mmf.CreateViewAccessor(0, 4); MemoryMappedViewAccessor accessor2ID = mmf.CreateViewAccessor(8, 4); MemoryMappedViewAccessor accessor3Data; //locked section using (new Niawa.Utilities.SingleGlobalInstance(1000, _ipcType)) //1000ms timeout on global lock { //get length, ID, and data msgLength = accessor1Len.ReadInt32(0); msgID = accessor2ID.ReadInt32(0); accessor3Data = mmf.CreateViewAccessor(16, msgLength); } //System.Diagnostics.Debug.WriteLine("MmfBufferedReader [Header]: HeaderID:" + msgID); //System.Diagnostics.Debug.WriteLine("MmfBufferedReader [Header]: LastHeaderID:" + _lastHeaderMsgID); //check if ID changed if (msgID == _lastHeaderMsgID) { //System.Diagnostics.Debug.WriteLine("MmfBufferedReader [Header]: There is no header work to do"); //do nothing return false; } else { //System.Diagnostics.Debug.WriteLine("MmfBufferedReader [Header]: Reading header"); //set ID _lastHeaderMsgID = msgID; //get data byte[] buffer = new byte[msgLength]; accessor3Data.ReadArray<byte>(0, buffer, 0, msgLength); NiawaMmfBufferHeader msg = new NiawaMmfBufferHeader(buffer); _previousCachedHeader = _cachedHeader; _cachedHeader = msg; return true; } }
/// <summary> /// Start reading the memory mapped file in a loop thread. /// </summary> public void StartListening() { try { logger.Info("[" + _description + "-M] Starting"); if (_threadStatus.IsThreadEnabled) { logger.Warn("[" + _description + "-M] Could not start: Reader thread was already active"); } else { //start thread t1 = new System.Threading.Thread(ListenThreadImpl); _receiveQueue.Clear(); _cachedHeader = InitializeCachedHeader(_cachedHeader); _previousCachedHeader = InitializeCachedHeader(_previousCachedHeader); _minimumMessageDate = DateTime.Now; _threadStatus.IsThreadEnabled = true; //start client t1.Start(); //thread status _threadStatus.Status = Niawa.Threading.ThreadStatus.STATUS_STARTED; } } catch (Exception ex) { logger.Error("[" + _description + "-M] Exception during start listening: " + ex.Message, ex); if (!_ignoreExceptions) throw ex; } }