private void sinkStorageStationIsReadyFired(ICDEThing sender, object pReady)
 {
     if (pReady != null)
     {
         if (MyTagLog == null)
         {
             MyTagLog = new TheStorageMirror <TheNMITagLogEntry>(TheCDEngines.MyIStorageService)
             {
                 IsRAMStore = true
             };
             MyTagLog.SetRecordExpiration(600, null);
             MyTagLog.IsCachePersistent        = true;
             MyTagLog.CacheStoreInterval       = 50;
             MyTagLog.IsStoreIntervalInSeconds = true;
             MyTagLog.CacheTableName           = "TagLog" + MyBaseThing.ID;
             if (!MyTagLog.IsRAMStore)
             {
                 MyTagLog.CreateStore("Live Tag Log", "Historian of Live Tags", null, true, false);
             }
             else
             {
                 MyTagLog.InitializeStore(true, false);
             }
         }
         mIsInitialized = true;
         FireEvent(eThingEvents.Initialized, this, true, true);
     }
 }
        private void sinkStorageStationIsReadyFired(ICDEThing sender, object pReady)
        {
            if (pReady != null)
            {
                if (MyRuleEventLog == null)
                {
                    MyRuleEventLog = new TheStorageMirror <TheEventLogData>(TheCDEngines.MyIStorageService);
                    MyRuleEventLog.CacheTableName = "EventLog";
                    MyRuleEventLog.UseSafeSave    = true;
                    MyRuleEventLog.SetRecordExpiration(604800, null);
                    MyRuleEventLog.CacheStoreInterval       = 15;
                    MyRuleEventLog.IsStoreIntervalInSeconds = true;
                    MyRuleEventLog.AppendOnly = true;

                    if (!MyRuleEventLog.IsRAMStore)
                    {
                        MyRuleEventLog.CreateStore("The Event Log", "History of events fired by the RulesEngine", null, true, TheBaseAssets.MyServiceHostInfo.IsNewDevice);
                    }
                    else
                    {
                        MyRuleEventLog.InitializeStore(true, TheBaseAssets.MyServiceHostInfo.IsNewDevice);
                    }
                    LogEvent(new TheEventLogData
                    {
                        EventCategory = eLoggerCategory.EngineEvent,
                        EventTime     = DateTimeOffset.Now,
                        StationName   = TheBaseAssets.MyServiceHostInfo?.GetPrimaryStationURL(false),
                        EventName     = "Event Log Started"
                    });
                }
            }
        }
Beispiel #3
0
 private void StorageHasStarted(ICDEThing sender, object pReady)
 {
     if (pReady != null)
     {
         if (MyServiceHealthDataStore == null)
         {
             MyServiceHealthDataStore = new TheStorageMirror <TheThingStore>(TheCDEngines.MyIStorageService)
             {
                 IsRAMStore        = "RAM".Equals(pReady.ToString()),
                 IsCachePersistent = "RAM".Equals(pReady.ToString()) && !TheBaseAssets.MyServiceHostInfo.IsCloudService,
                 CacheTableName    = "TheHealthHistory"
             };
             if (MyServiceHealthDataStore.IsRAMStore)
             {
                 MyServiceHealthDataStore.SetRecordExpiration(86400, null);   //RAM stores for 1 day
                 MyServiceHealthDataStore.InitializeStore(true, false);
             }
             else
             {
                 MyServiceHealthDataStore.SetRecordExpiration(604800, null); //Storage stores for 7 days
                 MyServiceHealthDataStore.CreateStore("C-DMyComputer: DeviceHealthData", "All health Data of a Device/Service", null, true, false);
             }
             TheBaseAssets.MySYSLOG.WriteToLog(8002, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("jcHealth", "Health Storage Started", eMsgLevel.l3_ImportantMessage));
         }
     }
 }
 private void sinkStorageStationIsReadyFired(ICDEThing sender, object pReady)
 {
     if (pReady != null)
     {
         if (MySensorStore == null)
         {
             MySensorStore = new TheStorageMirror <TheSensorValue>(TheCDEngines.MyIStorageService);
             if (MyBaseEngine.GetEngineState().IsSimulated || "RAM".Equals(pReady.ToString()))
             {
                 MySensorStore.IsRAMStore        = true;
                 MySensorStore.IsCachePersistent = true;
                 MySensorStore.SetRecordExpiration(10000, null);
             }
             else
             {
                 MySensorStore.IsRAMStore = false;
             }
             if (!MySensorStore.IsRAMStore && MyBaseEngine.GetEngineState().IsService)
             {
                 MySensorStore.CreateStore("Sensor Data: Sensor Data Store", "Data from sensors", null, true, false);
             }
             else
             {
                 MySensorStore.InitializeStore(true, false);
             }
         }
     }
 }
 public TheSessionStateManager(TheServiceHostInfo pSiteID)
 {
     MySite          = pSiteID;
     MySessionStates = new TheStorageMirror <TheSessionState>(TheCDEngines.MyIStorageService)
     {
         IsRAMStore = true, BlockWriteIfIsolated = true
     };
     MySessionStates.SetRecordExpiration(TheBaseAssets.MyServiceHostInfo.SessionTimeout, sinkExpired);
     MySessionStates.InitializeStore(true);
 }
 private void OnStorageReady(ICDEThing pThing, object para)
 {
     MyFootPrints = new TheStorageMirror <TheFootPrints>(TheCDEngines.MyIStorageService)
     {
         CacheTableName    = MyNodePrintsName,
         IsRAMStore        = true,
         IsCachePersistent = true
     };
     MyFootPrints.InitializeStore(false, false);
 }
Beispiel #7
0
 private void OnStorageReady(ICDEThing pThing, object para)
 {
     MyLogFiles = new TheStorageMirror <TheBackupDefinition>(TheCDEngines.MyIStorageService)
     {
         CacheTableName     = MyLogFilesTableName,
         IsRAMStore         = true,
         IsCachePersistent  = false,
         CacheStoreInterval = 0
     };
     MyLogFiles.RegisterEvent(eStoreEvents.StoreReady, sinkStorageReady);
     MyLogFiles.RegisterEvent(eStoreEvents.DeleteRequested, sinkDeleteLog);
     MyLogFiles.RegisterEvent(eStoreEvents.ReloadRequested, sinkStorageReady);
     MyLogFiles.InitializeStore(false, false);
 }
Beispiel #8
0
 //Helper Function
 private void SetupStorageMirror()
 {
     MyScriptTableStorage = new TheStorageMirror <ScriptSnapshot>(TheCDEngines.MyIStorageService)
     {
         IsRAMStore               = true,
         IsCachePersistent        = true,
         IsStoreIntervalInSeconds = true,
         CacheTableName           = $"ScriptTableFields{MyBaseThing.ID}"
     };
     MyScriptTableStorage.RegisterEvent(eStoreEvents.StoreReady, SinkStoreReady);
     MyScriptTableStorage.InitializeStore(new TheStorageMirrorParameters {
         TrackInsertionOrder = true,
         CanBeFlushed        = true,
         ResetContent        = false
     });
 }
        /// <summary>
        /// Returns false if stores could not be initalized - IStorageService failed and will be shutdown
        /// </summary>
        /// <returns></returns>
        private bool InitializeStores()
        {
            bool bInitialized = CreateStorageDAT();

            if (!bInitialized)
            {
                return(false);
            }
            bool Success = true;

#if JCR_TESTSTORE
            if (MyTESTBASE == null)
            {
                MyTESTBASE            = new TheStorageMirror <TheTestBase>(this);
                MyTESTBASE.IsRAMStore = MyBaseEngine.GetEngineState().IsSimulated;
                if (MyBaseEngine.GetEngineState().IsService)
                {
                    MyTESTBASE.CreateStore(TheBaseAssets.MyServiceHostInfo.ApplicationName + ": Test Store", "Test Push and other test messages", null);
                }
                else
                {
                    MyTESTBASE.InitializeStore();
                }
            }
#endif
            if (MyBaseEngine.GetEngineState().IsService&& TheBaseAssets.MyServiceHostInfo.StoreLoggedMessages)
            {
                EdgeDataCreateStore(typeof(TSM), null, TheBaseAssets.MyServiceHostInfo.ApplicationName + ": SystemMessageLog", "Log of all Application System Messages", false, null, null);
            }

            if (MyTimedCallbacks == null)
            {
                MyTimedCallbacks = new TheStorageMirror <TheTimedCallback>(TheCDEngines.MyIStorageService)
                {
                    IsRAMStore = true
                };
                MyTimedCallbacks.InitializeStore(true);
                MyTimedCallbacks.SetRecordExpiration(TheBaseAssets.MyServiceHostInfo.TO.ReceivedChunkTimeout, null);
            }
            if (TheCommonUtils.CBool(TheBaseAssets.MySettings.GetSetting("UseStorageForThingRegistry")))
            {
                Success = CreateThingRegistryStore();
            }
            return(Success);
        }
        private void CreateTHHUx(string tGuid, string FileToImport)
        {
            var MyServiceHealthDataStore = new TheStorageMirror <TheThingStore>(TheCDEngines.MyIStorageService);

            MyServiceHealthDataStore.IsRAMStore               = true;
            MyServiceHealthDataStore.IsCachePersistent        = true;
            MyServiceHealthDataStore.CacheStoreInterval       = 200;
            MyServiceHealthDataStore.IsStoreIntervalInSeconds = true;
            MyServiceHealthDataStore.CacheTableName           = tGuid;
            MyServiceHealthDataStore.InitializeStore(true, false, FileToImport);

            int tBS = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "ChartValues");

            if (tBS < 10)
            {
                tBS = 10;
            }
            if (tBS > 10000)
            {
                tBS = 10000;
            }


            int tCS = (int)TheThing.GetSafePropertyNumber(MyBaseThing, "ChartSize");

            if (tCS < 6)
            {
                tCS = 6;
            }

            TheNMIEngine.AddChartScreen(MyBaseThing, new TheChartDefinition(TheThing.GetSafeThingGuid(MyBaseThing, tGuid), tGuid, tBS, tGuid, true, "", "PB.HostAddress", "PB.QSenders,PB.QSLocalProcessed,PB.QSSent,PB.QKBSent,PB.QKBReceived,PB.QSInserted,PB.EventTimeouts,PB.TotalEventTimeouts,PB.CCTSMsRelayed,PB.CCTSMsReceived,PB.CCTSMsEvaluated,PB.HTCallbacks,PB.KPI1,PB.KPI2,PB.KPI3,PB.KPI4,PB.KPI5,PB.KPI10")
            {
                GroupMode = 0, IntervalInMS = 0
            }, 5, 3, 0, "Customer KPIs", false, new ThePropertyBag()
            {
                ".TileHeight=8", ".NoTE=true", ".TileWidth=" + tCS
            });
        }
 internal TheSystemMessageLog(int MaxEntries, bool UseQueue = false)
 {
     UseSysLogQueue = UseQueue;
     if (UseSysLogQueue)
     {
         InitDequeue();
     }
     if (MaxEntries == 0)
     {
         MaxEntries = 500;
     }
     MyMessageLog = new TheStorageMirror <TheEventLogEntry>(TheCDEngines.MyIStorageService)
     {
         IsRAMStore = true, BlockWriteIfIsolated = true
     };
     MyMessageLog.InitializeStore(true);
     SetMaxLogEntries(MaxEntries);
     if (LogWriteBuffer > 0 && LogWriteBuffer < 10)
     {
         LogWriteBuffer = 10;
     }
     LogFilePath = null;
 }
Beispiel #12
0
        private void StartUPnPDiscovery(string pLiveEngines)
        {
            if (MyUPnPDiscoveryPast != null)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(109, new TSM("UPnP", "DISCO aready running!"));
                return;
            }
            MyUPnPDiscoveryPast = new TheStorageMirror <TheUPnPDeviceInfo>(Engines.TheCDEngines.MyIStorageService)
            {
                IsRAMStore = true, BlockWriteIfIsolated = true
            };
            MyUPnPDiscoveryPast.SetRecordExpiration(DISCOExpireTime, sinkDeviceExpired);
            //MyUPnPDiscoveryPast.CacheStoreInterval = 60;
            //MyUPnPDiscoveryPast.IsStoreIntervalInSeconds = true;
            //MyUPnPDiscoveryPast.IsCachePersistent = true;
            MyUPnPDiscoveryPast.InitializeStore(true, true);

            var tCDEConnectUrl = TheBaseAssets.MyServiceHostInfo.GetPrimaryStationURL(false);

            TheBaseAssets.MySYSLOG.WriteToLog(107, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("UPnP", "Starting Device", eMsgLevel.l3_ImportantMessage));
            MyDeviceUPnPInfo = new TheUPnPDeviceInfo()
            {
                FriendlyName    = TheBaseAssets.MyServiceHostInfo.ApplicationTitle + " at: " + tCDEConnectUrl + " - Services:" + pLiveEngines,// pStationEngines;
                Manufacturer    = TheBaseAssets.MyServiceHostInfo.VendorName,
                ManufacturerUrl = TheBaseAssets.MyServiceHostInfo.VendorUrl,
                ModelName       = TheBaseAssets.MyServiceHostInfo.ApplicationName,
                ModelNumber     = string.Format("V{0:0.0000}", TheBaseAssets.MyServiceHostInfo.CurrentVersion),
                SerialNumber    = TheBaseAssets.CurrentVersionInfo,
                PacketString    = "",
                RawMetaXml      = "",
                LocationURL     = tCDEConnectUrl,
                ST            = "C-DEngine",
                CDEConnectUrl = tCDEConnectUrl,
                CDENodeID     = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID,
                UUID          = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString(),
                USN           = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString(),
                IsCDEngine    = true
            };
            if (!TheBaseAssets.MyServiceHostInfo.RequiresConfiguration)
            {
                MyDeviceUPnPInfo.CDEContextID = TheBaseAssets.MyScopeManager.GetScrambledScopeID();     //GRSI: rare
            }
            if (TheCommonUtils.IsHostADevice())
            {
                MyDeviceUPnPInfo.HasPresentation = false;
            }
            else
            {
                if (!TheBaseAssets.MyServiceHostInfo.DisableWebSockets && TheBaseAssets.MyServiceHostInfo.MyStationWSPort > 0)
                {
                    var builder = new UriBuilder(TheBaseAssets.MyServiceHostInfo.GetPrimaryStationURL(false));
                    builder.Scheme = builder.Scheme == "https" ? "wss" : "ws";
                    builder.Port   = TheBaseAssets.MyServiceHostInfo.MyStationWSPort;
                    MyDeviceUPnPInfo.CDEConnectWsUrl = TheCommonUtils.TruncTrailingSlash(builder.Uri.ToString());
                }
                MyDeviceUPnPInfo.HasPresentation = true;
            }
            eventDiscoReady?.Invoke(true);

            TheQueuedSenderRegistry.RegisterHealthTimer(DoScan4Devices);
            TheBaseAssets.MySYSLOG.WriteToLog(108, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("UPnP", "DISCO engine ready..."));
        }
        public void AddItemsToTheStorageMirrorTest()
        {
            #region ASSEMBLE

            TheStorageMirror <TheStorageEngineTSM> .StoreResponse response = null;
            int totalCandidates       = 5000;
            var random                = new Random();
            var data                  = Enumerable.Range(1, totalCandidates).OrderBy(i => random.Next(1, totalCandidates));
            ManualResetEventSlim gate = new ManualResetEventSlim();
            TheStorageMirror <TheStorageEngineTSM> mirror;
            List <TheStorageEngineTSM>             TSMs = new List <TheStorageEngineTSM>();


            // Build the collection of TSMs
            foreach (var payload in data)
            {
                TSMs.Add(new TheStorageEngineTSM()
                {
                    TXTPattern = payload.ToString()
                });
            }

            // Spin up your mirror
            mirror = new TheStorageMirror <TheStorageEngineTSM>(TheCDEngines.MyIStorageService)
            {
                IsRAMStore               = true,
                CacheStoreInterval       = 1,
                IsStoreIntervalInSeconds = true,
                IsCachePersistent        = true,
                UseSafeSave              = true,
                AllowFireUpdates         = true,
            };
            mirror.RegisterEvent(eStoreEvents.StoreReady, e => { gate.Set(); });
            mirror.InitializeStore(true);

            // Wait for mirror to initialize...
            gate.Wait(30000);

            #endregion

            #region ACT

            // Add your items
            Task.Factory.StartNew(() =>
            {
                mirror.AddItems(TSMs, payload =>
                {
                    response = payload;
                    gate.Set();
                });
            });

            //Wait for response
            gate.Reset();
            gate.Wait(30000);

            mirror?.Dispose();

            #endregion

            #region ASSERT

            Assert.IsFalse(response.HasErrors);

            #endregion
        }
        public override bool Init()
        {
            if (mIsInitCalled)
            {
                return(false);
            }
            mIsInitCalled = true;

            MyBaseThing.LastMessage = "Device Ready";
            MyBaseThing.StatusLevel = 0;
            IsConnected             = false;

            MyBaseThing.DeclareConfigProperty(new TheThing.TheConfigurationProperty {
                Name = nameof(MyBaseThing.Address), cdeT = ePropertyTypes.TString, Required = true, Description = "", Generalize = true
            });
            MyBaseThing.DeclareConfigProperty(new TheThing.TheConfigurationProperty {
                Name = nameof(MyBaseThing.FriendlyName), cdeT = ePropertyTypes.TString, Description = ""
            });
            MyBaseThing.DeclareConfigProperty(new TheThing.TheConfigurationProperty {
                Name = nameof(Interval), cdeT = ePropertyTypes.TNumber, DefaultValue = 1000, RangeMin = 100, Description = "Time interval at which to poll the sensor for values"
            });
            MyBaseThing.DeclareConfigProperty(new TheThing.TheConfigurationProperty {
                Name = nameof(CustomPort), cdeT = ePropertyTypes.TNumber, DefaultValue = 502, Description = ""
            });
            MyBaseThing.DeclareConfigProperty(new TheThing.TheConfigurationProperty {
                Name = nameof(SlaveAddress), cdeT = ePropertyTypes.TNumber, DefaultValue = 1, Description = ""
            });
            MyBaseThing.DeclareConfigProperty(new TheThing.TheConfigurationProperty {
                Name = nameof(AutoConnect), cdeT = ePropertyTypes.TBoolean, DefaultValue = false, Description = ""
            });
            MyBaseThing.DeclareConfigProperty(new TheThing.TheConfigurationProperty {
                Name = nameof(KeepOpen), cdeT = ePropertyTypes.TBoolean, DefaultValue = true, Description = ""
            });
            MyBaseThing.DeclareConfigProperty(new TheThing.TheConfigurationProperty {
                Name = nameof(Offset), cdeT = ePropertyTypes.TNumber, Description = ""
            });
            MyBaseThing.DeclareConfigProperty(new TheThing.TheConfigurationProperty {
                Name = nameof(ConnectionType), cdeT = ePropertyTypes.TNumber, DefaultValue = 3, Description = "Read Coils:1, Read Input:2, Holding Registers:3, Input Register:4, Read Multiple Register:23"
            });

            MyModFieldStore                          = new TheStorageMirror <FieldMapping>(TheCDEngines.MyIStorageService);
            MyModFieldStore.IsRAMStore               = true;
            MyModFieldStore.IsCachePersistent        = true;
            MyModFieldStore.IsStoreIntervalInSeconds = true;
            if (string.IsNullOrEmpty(MyBaseThing.ID))
            {
                MyBaseThing.ID = Guid.NewGuid().ToString();
                if (MyDevice != null && !string.IsNullOrEmpty(MyDevice.Id))
                {
                    MyBaseThing.ID = MyDevice.Id;
                }
                if (GetProperty("CustomPort", false) == null)
                {
                    TheThing.SetSafePropertyNumber(MyBaseThing, "CustomPort", 502);
                }
                if (GetProperty("SlaveAddress", false) == null)
                {
                    TheThing.SetSafePropertyNumber(MyBaseThing, "SlaveAddress", 1);
                }
                Interval = 1000;
            }
            MyModFieldStore.CacheTableName = $"MBFLDS{MyBaseThing.ID}";
            MyModFieldStore.RegisterEvent(eStoreEvents.StoreReady, sinkStoreReady);
            MyModFieldStore.RegisterEvent(eStoreEvents.UpdateRequested, sinkUpdated);
            MyModFieldStore.RegisterEvent(eStoreEvents.Inserted, sinkUpdated);
            MyModFieldStore.InitializeStore(true, false);
            return(false);
        }
Beispiel #15
0
        protected virtual bool InitBase(string friendlyNamePrefix, string deviceType)
        {
            if (TheCommonUtils.CGuid(MyBaseThing.ID) == Guid.Empty)
            {
                MyBaseThing.ID = Guid.NewGuid().ToString();
                if (string.IsNullOrEmpty(MyBaseThing.FriendlyName))
                {
                    MyBaseThing.FriendlyName = $"{friendlyNamePrefix}: {MyBaseThing.ID}";
                }
            }

            MyBaseThing.LastUpdate = DateTimeOffset.Now;

            MyBaseThing.EngineName = MyBaseEngine.GetEngineName();
            MyBaseThing.DeviceType = deviceType;

            TheBaseEngine.WaitForStorageReadiness((pThing, pReady) =>
            {
                if (pReady != null)
                {
                    var receiverThings                      = new TheStorageMirror <TConnectionThing>(TheCDEngines.MyIStorageService);
                    receiverThings.CacheTableName           = nameof(TConnectionThing) + TheThing.GetSafeThingGuid(MyBaseThing, nameof(TConnectionThing));
                    receiverThings.IsRAMStore               = true;
                    receiverThings.CacheStoreInterval       = 1;
                    receiverThings.IsStoreIntervalInSeconds = true;
                    receiverThings.IsCachePersistent        = true;
                    receiverThings.UseSafeSave              = true;
                    receiverThings.RegisterEvent(eStoreEvents.StoreReady, (args) =>
                    {
                        var result = args.Para as TSM;
                        if (result != null && result.LVL == eMsgLevel.l1_Error)
                        {
                            MyBaseThing.SetStatus(3, "Error loading things");
                            TheBaseAssets.MySYSLOG.WriteToLog(98201, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM(MyBaseThing.EngineName, "Initialization", eMsgLevel.l6_Debug, String.Format("Error loading things for connection {0}", this.GetBaseThing().Address)));
                        }
                        else
                        {
                            MyConnectionThings = receiverThings;
                            if (MyConnectionThingsForm != null)
                            {
                                MyConnectionThingsForm.defDataSource = MyConnectionThings.StoreMID.ToString();
                            }
                            TheBaseAssets.MySYSLOG.WriteToLog(95272, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM(MyBaseThing.EngineName, "Initialization", eMsgLevel.l6_Debug, String.Format("Things loaded for connection {0}", this.GetBaseThing().Address)));

                            if (AutoConnect)
                            {
                                Connect();
                                if (!IsConnected)
                                {
                                    TheCommonUtils.cdeRunTaskAsync("receiverAutoConnect", async o =>
                                    {
                                        await TheCommonUtils.TaskDelayOneEye(30000, 100).ConfigureAwait(false);
                                        while (!IsConnected && AutoConnect && TheBaseAssets.MasterSwitch)
                                        {
                                            Connect();
                                            await TheCommonUtils.TaskDelayOneEye(30000, 100).ConfigureAwait(false);
                                        }
                                    }).ContinueWith(t => t.Exception);
                                }
                            }
                            mIsInitialized = true;
                            FireEvent(eThingEvents.Initialized, this, true, true);
                            FireEvent("ServerInit", this, IsConnected.ToString(), true);
                        }
                    }
                                                 );
                    receiverThings.InitializeStore(false, false);
                }
            }, true);
            return(mIsInitialized);
        }
        public void GetRecordsFromTheStorageMirrorTest(
            [Values(0, 500, 5000)] int maxCount,
            [Values(50, 5000)] int totalCandidates
            )
        {
            #region ASSEMBLE

            TheStorageMirror <TheStorageEngineTSM> .StoreResponse response = null;
            var random = new Random();
            var data   = Enumerable.Range(1, totalCandidates).OrderBy(i => random.Next(1, totalCandidates));
            ManualResetEventSlim gate = new ManualResetEventSlim();
            TheStorageMirror <TheStorageEngineTSM> mirror;
            List <TheStorageEngineTSM>             TSMs = new List <TheStorageEngineTSM>();

            // Build the collection of TSMs
            foreach (var payload in data)
            {
                TSMs.Add(new TheStorageEngineTSM()
                {
                    cdeMID     = Guid.NewGuid(),
                    TXTPattern = payload.ToString()
                });
            }

            // Spin up your mirror
            mirror = new TheStorageMirror <TheStorageEngineTSM>(TheCDEngines.MyIStorageService)
            {
                IsRAMStore               = true,
                CacheStoreInterval       = 1,
                IsStoreIntervalInSeconds = true,
                IsCachePersistent        = true,
                UseSafeSave              = true,
                AllowFireUpdates         = true,
            };
            if (maxCount > 0)
            {
                mirror.SetMaxStoreSize(maxCount);
            }
            mirror.RegisterEvent(eStoreEvents.StoreReady, e => { gate.Set(); });
            mirror.InitializeStore(true);

            // Wait for mirror to initialize...
            gate.Wait(30000);

            // Add your items
            Task.Factory.StartNew(() =>
            {
                mirror.AddItems(TSMs, payload =>
                {
                    response = payload;
                    gate.Set();
                });
            });

            //Wait for response
            gate.Reset();
            gate.Wait(30000);
            if ((response != null) && response.HasErrors)
            {
                Assert.Fail("Unable to add test collection items! Reason: {0}", response.ErrorMsg);
            }

            #endregion

            #region ACT

            // Attempt to retrieve your items
            Task.Factory.StartNew(() =>
            {
                mirror.GetRecords(payload =>
                {
                    response = payload;
                    gate.Set();
                },
                                  true);
            });

            // Wait for response
            gate.Reset();
            gate.Wait(30000);
            if ((response != null) && response.HasErrors)
            {
                Assert.Fail("Unable to retrieve items! Reason: {0}", response.ErrorMsg);
            }

            mirror?.Dispose();

            #endregion

            #region ASSERT

            var expectedCount = maxCount == 0 ? totalCandidates : Math.Min(maxCount, totalCandidates);

            Assert.AreEqual(expectedCount, response.MyRecords.Count, "Not all test records were not added successfully.");

            #endregion
        }
        public void RemoveAnItemByIDFromTheStorageMirrorTest()
        {
            #region ASSEMBLE

            TheStorageMirror <TheStorageEngineTSM> .StoreResponse response = null;
            int totalCandidates       = 5000;
            int indexMiddle           = totalCandidates / 2;
            int indexCurrent          = 0;
            var random                = new Random();
            var data                  = Enumerable.Range(1, totalCandidates).OrderBy(i => random.Next(1, totalCandidates));
            ManualResetEventSlim gate = new ManualResetEventSlim();
            TheStorageMirror <TheStorageEngineTSM> mirror;
            TheStorageEngineTSM        tsmCurrent = null;
            TheStorageEngineTSM        tsmMiddle  = null;
            TheStorageEngineTSM        tsmMatch   = null;
            List <TheStorageEngineTSM> TSMs       = new List <TheStorageEngineTSM>();
            List <TheStorageEngineTSM> myRecords  = new List <TheStorageEngineTSM>();

            // Build the collection of TSMs and cache the middle one
            foreach (var payload in data)
            {
                tsmCurrent = new TheStorageEngineTSM()
                {
                    cdeMID     = Guid.NewGuid(),
                    TXTPattern = payload.ToString()
                };
                TSMs.Add(tsmCurrent);
                if ((indexCurrent++ >= indexMiddle) && (tsmMiddle == null))
                {
                    tsmMiddle = tsmCurrent;
                }
            }
            if (tsmMiddle == null)
            {
                Assert.Fail("Unable to cache the middle TSM!");
            }

            // Spin up your mirror
            mirror = new TheStorageMirror <TheStorageEngineTSM>(TheCDEngines.MyIStorageService)
            {
                IsRAMStore               = true,
                CacheStoreInterval       = 1,
                IsStoreIntervalInSeconds = true,
                IsCachePersistent        = true,
                UseSafeSave              = true,
                AllowFireUpdates         = true,
            };
            mirror.RegisterEvent(eStoreEvents.StoreReady, e => { gate.Set(); });
            mirror.InitializeStore(true);

            // Wait for mirror to initialize...
            gate.Wait(30000);

            // Add your items
            Task.Factory.StartNew(() =>
            {
                mirror.AddItems(TSMs, payload =>
                {
                    response = payload;
                    gate.Set();
                });
            });

            //Wait for response
            gate.Reset();
            gate.Wait(30000);
            if ((response != null) && response.HasErrors)
            {
                Assert.Fail("Unable to add test collection items! Reason: {0}", response.ErrorMsg);
            }

            #endregion

            #region ACT

            // Attempt to remove your middle item
            Task.Factory.StartNew(() =>
            {
                mirror.RemoveAnItemByID(tsmMiddle.cdeMID, payload =>
                {
                    response = payload;
                    gate.Set();
                });
            });

            // Wait for response
            gate.Reset();
            gate.Wait(30000);
            if ((response != null) && response.HasErrors)
            {
                Assert.Fail("Unable to remove item by ID! Reason: {0}", response.ErrorMsg);
            }

            // Attempt to retrieve your middle item
            tsmMatch = mirror.GetEntryByID(tsmMiddle.cdeMID);

            mirror?.Dispose();

            #endregion

            #region ASSERT

            Assert.IsTrue(tsmMatch == null);

            #endregion
        }