///<Summary>Checks bugIDs in list for incompletes. Returns false if incomplete exists.</Summary> public static bool CheckForCompletion(List <long> listBugIDs) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetBool(MethodBase.GetCurrentMethod(), listBugIDs)); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "SELECT COUNT(*) FROM bug " + "WHERE VersionsFixed='' " + "AND BugId IN (" + String.Join(",", listBugIDs) + ")"; o.Tag = Db.GetCount(command); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "bugsCheckForCompletionThread"; odThread.Start(true); if (!odThread.Join(THREAD_TIMEOUT)) { return(true); } if (PIn.Int(odThread.Tag.ToString()) != 0) { return(false); } return(true); }
///<Summary>Gets name from database. Not very efficient.</Summary> public static string GetSubmitterName(long submitter) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetString(MethodBase.GetCurrentMethod(), submitter)); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "SELECT UserName FROM buguser WHERE BugUserId=" + submitter; o.Tag = Db.GetScalar(command); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "bugsGetSubmitterNameThread"; odThread.Start(true); if (!odThread.Join(THREAD_TIMEOUT)) { return(""); } return(odThread.Tag.ToString()); }
///<summary>Must pass in version as "Maj" or "Maj.Min" or "Maj.Min.Rev". Uses like operator. Can return null if the thread fails to join.</summary> public static List <Bug> GetByVersion(string versionMajMin, string filter = "") { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <List <Bug> >(MethodBase.GetCurrentMethod(), versionMajMin, filter)); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "SELECT * FROM bug WHERE (VersionsFound LIKE '" + POut.String(versionMajMin) + "%' OR VersionsFound LIKE '%;" + POut.String(versionMajMin) + "%' OR " + "VersionsFixed LIKE '" + POut.String(versionMajMin) + "%' OR VersionsFixed LIKE '%;" + POut.String(versionMajMin) + "%') "; if (filter != "") { command += "AND Description LIKE '%" + POut.String(filter) + "%'"; } o.Tag = Crud.BugCrud.SelectMany(command); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "bugsGetByVersionThread"; odThread.Start(true); if (!odThread.Join(THREAD_TIMEOUT)) { return(null); } return((List <Bug>)odThread.Tag); }
///<summary>Gets one Bug from the db. Can return null if the thread fails to join.</summary> public static Bug GetOne(long bugId) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <Bug>(MethodBase.GetCurrentMethod(), bugId)); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif o.Tag = Crud.BugCrud.SelectOne(bugId); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "bugsGetOneThread"; odThread.Start(true); if (!odThread.Join(THREAD_TIMEOUT)) { return(null); } return((Bug)odThread.Tag); }
///<summary>Can return null if the thread fails to join.</summary> public static List <Bug> GetAll() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <List <Bug> >(MethodBase.GetCurrentMethod())); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "SELECT * FROM bug ORDER BY CreationDate DESC"; o.Tag = Crud.BugCrud.TableToList(DataCore.GetTable(command)); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "bugsGetAllThread"; odThread.Start(true); if (!odThread.Join(THREAD_TIMEOUT)) { return(null); } return((List <Bug>)odThread.Tag); }
///<summary></summary> private string RunWebMethod(Func <string> funcWebMethod) { Exception ex = null; RemotingRole remotingRoleCur = RemotingClient.RemotingRole; //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Change the remoting role to ServerWeb (this will get set back to remotingRoleCur later. RemotingClient.RemotingRole = RemotingRole.ServerWeb; //Set new database connection settings if designated. E.g. some unit tests need to set and utilize userLow and passLow. if (!string.IsNullOrEmpty(_server) && !string.IsNullOrEmpty(_db) && !string.IsNullOrEmpty(_user)) { new DataConnection().SetDbT(_server, _db, _user, _password, _userLow, _passLow, DatabaseType.MySql); } //Execute the func that was passed in now that our remoting role and database connection are correct. o.Tag = funcWebMethod(); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { ex = e; //Cannot throw exception here due to still being in a threaded context. })); if (ex != null) { throw ex; //Should never happen because this would be a "web exception" as in the ProcessRequest could not even invoke or something like that. } odThread.Name = "threadMiddleTierUnitTestRunWebMethod"; //Set the remoting role back after exiting the thread. odThread.AddExitHandler((e) => RemotingClient.RemotingRole = remotingRoleCur); odThread.Start(true); odThread.Join(System.Threading.Timeout.Infinite); return((string)odThread.Tag); }
///<summary>Wrapper method to call the passed-in func in a seperate thread connected to the reporting server. ///This method should only be used for SELECT, with the exception DashboardAR. Using this for create/update/delete may cause duplicates. ///The return type of this function is whatever the return type of the method you passed in is. ///Throws an exception if anything went wrong executing func within the thread.</summary> ///<param name="doRunOnReportServer">If this false, the func will run against the currently connected server.</param> public static T RunFuncOnReportServer <T>(Func <T> func, bool doRunOnReportServer = true) { if (!doRunOnReportServer) { return(func()); } Exception ex = null; ODThread threadGetTable = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { DataAction.Run(() => { o.Tag = func(); } //set the tag to the func's output. , ConnectionNames.DentalOfficeReportServer); //run on the report server. if not set up, automatically runs on the current server. })); threadGetTable.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { ex = e; })); threadGetTable.Name = "ReportComplexGetTableThread"; threadGetTable.Start(true); threadGetTable.Join(Timeout.Infinite); //Now that we are back on the main thread, it is now safe to throw exceptions. if (ex != null) { ExceptionDispatchInfo.Capture(ex.InnerException ?? ex).Throw(); //This preserves the stack trace of the InnerException. } return((T)threadGetTable.Tag); }
///<Summary>Will not mark completed feature requests as approved.</Summary> public static void MarkAsApproved(List <long> listRequestIDs) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), listRequestIDs); return; } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "UPDATE request SET Approval=7 " //Approved + "WHERE Approval!=9 " //9=Complete + "AND RequestId IN (" + String.Join(",", listRequestIDs) + ")"; o.Tag = Db.NonQ(command); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "featureMarkAsInProgressThread"; odThread.Start(true); if (!odThread.Join(2000)) //Give this thread up to 2 seconds to complete. { return; } }
///<Summary></Summary> public static void CompleteRequests(List <long> listRequestIDs, string versionText) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), listRequestIDs, versionText); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string versionString = "\r\n\r\nCompleted in version " + versionText; string command = "UPDATE request SET Approval=9, " //Complete + "Detail=CONCAT( Detail , '" + versionString + "' ) " + "WHERE RequestId IN (" + String.Join(",", listRequestIDs) + ")"; o.Tag = Db.NonQ(command); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "featureCheckForCompletionThread"; odThread.Start(true); if (!odThread.Join(2000)) //Give this thread up to 2 seconds to complete. { return; } }
///<summary>Returns a fully formatted string of the most recent unreleased versions, from 1 to 3.</summary> public static string GetLastReleases(int versionsRequested) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetString(MethodBase.GetCurrentMethod(), versionsRequested)); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "SELECT * FROM versionrelease " + "WHERE DateRelease < '1880-01-01' " //we are only interested in non-released versions. + "AND IsForeign=0 "; //Exclude black listed versions. for (int i = 0; i < _versionsBlackList.Count; i++) { command += "AND (MajorNum,MinorNum) != (" + POut.Int(_versionsBlackList[i].Major) + "," + POut.Int(_versionsBlackList[i].Minor) + ") "; } command += "ORDER BY MajorNum DESC,MinorNum DESC,BuildNum DESC " + "LIMIT 3"; //Might not be 3. List <VersionRelease> releaseList = RefreshAndFill(command); string versionsString = ""; if (releaseList.Count > 2 && versionsRequested > 2) { versionsString += releaseList[2].MajorNum.ToString() + "." + releaseList[2].MinorNum.ToString() + "." + releaseList[2].BuildNum.ToString() + ".0"; } if (releaseList.Count > 1 && versionsRequested > 1) { if (versionsString != "") { versionsString += ";"; } versionsString += releaseList[1].MajorNum.ToString() + "." + releaseList[1].MinorNum.ToString() + "." + releaseList[1].BuildNum.ToString() + ".0"; } if (releaseList.Count > 0) { if (versionsString != "") { versionsString += ";"; } versionsString += releaseList[0].MajorNum.ToString() + "." + releaseList[0].MinorNum.ToString() + "." + releaseList[0].BuildNum.ToString() + ".0"; } o.Tag = versionsString; })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "versionGetterThread"; odThread.Start(true); if (!odThread.Join(2000)) //Give this thread up to 2 seconds to complete. { return(null); } return(odThread?.Tag?.ToString() ?? ""); //if either odThread or odThread.Tag is null, return empty string }
///<summary>The following test calls setDb within a child thread. This will change the static database connection for all threads. The ///parent thread, or any other thread already alive, should not have their context changed.</summary> public void ODThread_SetDb_ChildContext() { Exception ex = null; string methodName = MethodBase.GetCurrentMethod().Name; string databaseName = POut.String(methodName).ToLower(); string odThreadGroupName = methodName + "_GroupName"; string databaseMain = LargeTableHelper.GetCurrentDatabase(); //should be pointing to a 'unittestXXX' database Assert.IsFalse(string.IsNullOrEmpty(databaseMain)); try { ODThread odThreadAffect = new ODThread((o) => { string databaseBefore = LargeTableHelper.GetCurrentDatabase(); //should be pointing to a 'unittestXXX' database Assert.AreEqual(databaseMain, databaseBefore); ODThread odThreadChangeDb = new ODThread(workerChild => { //The parent thread needs to call SetDb on a different database than the main thread is connected to. CreateDatabaseIfNeeded(databaseName); new DataConnection().SetDb("localhost", databaseName, "root", "", "", "", DatabaseType.MySql); VerifyCurrentDatabaseName(databaseName); }); odThreadChangeDb.AddExceptionHandler(e => ex = e); odThreadChangeDb.Name = MethodBase.GetCurrentMethod().Name + "_Child"; odThreadChangeDb.GroupName = odThreadGroupName; //This thread needs to only start the above thread and then make sure it is still connected to the unittestXXX database when complete. odThreadChangeDb.Start(); odThreadChangeDb.Join(Timeout.Infinite); //Manually join the parent to the main thread so that we know for certain that our child thread exists. VerifyCurrentDatabaseName(databaseMain); }); odThreadAffect.AddExceptionHandler(e => ex = e); odThreadAffect.Name = MethodBase.GetCurrentMethod().Name + "_ThreadAffected"; odThreadAffect.Start(); odThreadAffect.Join(Timeout.Infinite); //The main thread should still be on the original database after this. VerifyCurrentDatabaseName(databaseMain); //Verify that new thread is not affected by the call to SetDb() from the child thread above. //You should only SetDb() once per application instance. //After that, it does nothing to any thread (existing or subsequent) but the thread that calls it. ODThread odThreadChangeDb1 = new ODThread(workerChild => { VerifyCurrentDatabaseName(databaseMain); }); odThreadChangeDb1.AddExceptionHandler(e => ex = e); odThreadChangeDb1.Name = MethodBase.GetCurrentMethod().Name + "_Child"; odThreadChangeDb1.GroupName = odThreadGroupName; odThreadChangeDb1.Start(); odThreadChangeDb1.Join(Timeout.Infinite); //Manually join the parent to the main thread so that we know for certain that our child thread exists. } catch (Exception e) { ex = e; } finally { DropDatabase(databaseName); } Assert.IsNull(ex, ex?.Message); //Asserts do not bubble up as expected to the main thread so do a manual assert at the end of the day. }
///<summary>Spawns a child thread, on which it sets a Userod object to the thread's value for Security.CurUser.</summary> public static Userod GetCurUserFromThread() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <Userod>(MethodBase.GetCurrentMethod())); } Userod user = null; ODThread thread = new ODThread((o) => { user = Security.CurUser; }); thread.Start(); thread.Join(1000); //Give the thread 1 second to finish so this test doesn't hang. return(user); }
///<summary>Adds an exception handler to the thread passed in, starts the thread, and then waits until the thread has finished executing. ///This is just a helper method that will throw any exception that occurs within the thread on the parent (usually main) thread. ///Throws exceptions.</summary> private static void ExecuteThread(ODThread thread) { Exception eFinal = null; thread.AddExceptionHandler((e) => { eFinal = e; }); thread.Start(true); //This is intended to be a blocking call so give the action as long as it needs to complete. thread.Join(Timeout.Infinite); if (eFinal != null) //We are back on the main thread so it is safe to throw. { throw new Exception(eFinal.Message, eFinal); } }
///<summary>ODThread should be able to catch all exceptions after abort is called on it. If this test fails, an exception is being thrown and ///not being caught from within ODThread.</summary> public void ODThread_CatchThreadAbortException() { bool result = true; ODThread thread = new ODThread(o => { try { Thread.Sleep(TimeSpan.FromMinutes(10)); } catch (Exception ex) { //The thread abort exception will come in here. Because of some code in this exception, a different type of exception is thrown. ex.DoNothing(); throw new Exception("Exception that is not a ThreadAbortException"); } }); thread.AddExceptionHandler(ex => { //If the exception handler is every reached, the exception caused by aborting was not caught correctly. result = false; }); thread.Start(); Thread.Sleep(TimeSpan.FromSeconds(1)); //Give the thread a chance to start. thread.Join(0); //Will cause abort to occur instantly. thread.Join(Timeout.Infinite); //Now actually join and wait for the thread to finish. Assert.IsTrue(result); }
///<summary>The ThreadStatic database context should be inherited by any child thread that is spawned.</summary> public void ODThread_SetDbT_ParentChildDatabaseContext() { Exception ex = null; string methodName = MethodBase.GetCurrentMethod().Name; string databaseName = POut.String(methodName).ToLower(); string odThreadGroupName = methodName + "_GroupName"; //The main thread needs to connect to a unique database that the child thread should NOT end up getting connected to. //Use a query to get our current database context because unit tests utilizes a connection string and we only care about DataConnection.Database string databaseMain = LargeTableHelper.GetCurrentDatabase(); //should be pointing to a 'unittestXXX' database Assert.IsFalse(string.IsNullOrEmpty(databaseMain)); try { ODThread odThreadParent = new ODThread(workerParent => { //The parent thread needs to connect to a database that the main thread is not connected to. CreateDatabaseIfNeeded(databaseName); new DataConnection().SetDbT("localhost", databaseName, "root", "", "", "", DatabaseType.MySql); VerifyCurrentDatabaseName(databaseName); //Now the parent should spawn a child thread which should default to the thread specific database connection from the parent. ODThread odThreadChild = new ODThread(workerChild => { //The child thread should default to the database context of its parent and NOT the database context from the main thread. VerifyCurrentDatabaseName(databaseName); }); odThreadChild.AddExceptionHandler(e => ex = e); odThreadChild.Name = MethodBase.GetCurrentMethod().Name + "_Child"; odThreadChild.GroupName = odThreadGroupName; odThreadChild.Start(); odThreadChild.Join(Timeout.Infinite); VerifyCurrentDatabaseName(databaseName); }); odThreadParent.AddExceptionHandler(e => ex = e); odThreadParent.Name = MethodBase.GetCurrentMethod().Name + "_Parent"; odThreadParent.GroupName = odThreadGroupName; odThreadParent.Start(); odThreadParent.Join(Timeout.Infinite); //Manually join the parent to the main thread so that we know for certain that our child thread exists. VerifyCurrentDatabaseName(databaseMain); } catch (Exception e) { ex = e; } finally { DropDatabase(databaseName); } Assert.IsNull(ex, ex?.Message); //Asserts do not bubble up as expected to the main thread so do a manual assert at the end of the day. }
///<summary>Returns a list of all versions ordered by MajorNum, MinorNum, BuildNum, and IsForeign.</summary> public static List <VersionRelease> Refresh() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <List <VersionRelease> >(MethodBase.GetCurrentMethod())); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif string command = "SELECT * FROM versionrelease "; //Exclude black listed versions. for (int i = 0; i < _versionsBlackList.Count; i++) { if (i == 0) { command += "WHERE "; } else { command += "AND "; } command += "(MajorNum,MinorNum) != (" + POut.Int(_versionsBlackList[i].Major) + "," + POut.Int(_versionsBlackList[i].Minor) + ") "; } //The order is very important to other entites calling this method. command += "ORDER BY MajorNum DESC,MinorNum DESC,BuildNum DESC,IsForeign"; o.Tag = RefreshAndFill(command); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "versionGetterThread"; odThread.Start(true); if (!odThread.Join(2000)) //Give this thread up to 2 seconds to complete. { return(null); } return((List <VersionRelease>)odThread.Tag); }
///<summary>Gets one EServiceSignalHQ from the serviceshq db located on SERVER184. Returns null in case of failure.</summary> public static EServiceMetrics GetEServiceMetricsFromSignalHQ() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <EServiceMetrics>(MethodBase.GetCurrentMethod())); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. new DataConnection().SetDbT("server184", "serviceshq", "root", "", "", "", DatabaseType.MySql, true); //See EServiceSignalHQs.GetEServiceMetrics() for details. string command = @"SELECT 0 EServiceSignalNum, h.* FROM eservicesignalhq h WHERE h.ReasonCode=1024 AND h.ReasonCategory=1 AND h.ServiceCode=2 AND h.RegistrationKeyNum=-1 ORDER BY h.SigDateTime DESC LIMIT 1" ; EServiceSignal eServiceSignal = Crud.EServiceSignalCrud.SelectOne(command); EServiceMetrics eServiceMetric = new EServiceMetrics(); if (eServiceSignal != null) { using (XmlReader reader = XmlReader.Create(new System.IO.StringReader(eServiceSignal.Tag))) { eServiceMetric = (EServiceMetrics) new XmlSerializer(typeof(EServiceMetrics)).Deserialize(reader); } eServiceMetric.IsValid = true; } o.Tag = eServiceMetric; })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "eServiceMetricsThread"; odThread.Start(true); if (!odThread.Join(2000)) //Give this thread up to 2 seconds to complete. { return(null); } EServiceMetrics retVal = (EServiceMetrics)odThread.Tag; return(retVal); }
///<summary></summary> private static string RunWebMethod(Func <string> funcWebMethod) { Exception ex = null; //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Change the thread static remoting role to ServerWeb and then execute the func that was passed in. RemotingClient.SetRemotingRoleT(RemotingRole.ServerWeb); o.Tag = funcWebMethod(); })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { ex = e; //Cannot throw exception here due to still being in a threaded context. })); if (ex != null) { throw ex; //Should never happen because this would be a "web exception" as in the ProcessRequest could not even invoke or something like that. } odThread.Name = "threadMiddleTierUnitTestRunWebMethod"; odThread.Start(true); odThread.Join(System.Threading.Timeout.Infinite); return((string)odThread.Tag); }
///<summary>Perform the given function in the context of the given connectionName db and return a T.</summary> private static T GetT <T>(Func <T> fn, Action aSetConnection) { Exception eFinal = null; //Reference types will be set to null. T ret = default(T); ODThread th = new ODThread(new ODThread.WorkerDelegate((thread) => { aSetConnection(); ret = fn(); })); th.AddExceptionHandler(new ODThread.ExceptionDelegate((e) => { eFinal = e; })); th.Start(true); //This is intended to be a blocking call so give the action as long as it needs to complete. th.Join(System.Threading.Timeout.Infinite); if (eFinal != null) //We are back on the main thread so it is safe to throw. { throw new Exception(eFinal.Message, eFinal); } return(ret); }
public void Reports_GetTable_MySqlUserLow() { Exception ex = null; //Spawn a new thread so that we don't manipulate any global DataConnection settings. ODThread thread = new ODThread(o => { //Prepare some simple queries to verify how both user and user low react. string tempTableName = "tmpreportsunittesttable"; string tempTableDropQuery = $"DROP TABLE IF EXISTS {tempTableName}"; string tempTableCreateQuery = $"CREATE TABLE {tempTableName} (Col1 VARCHAR(1))"; string tempTableShowQuery = $"SHOW TABLES LIKE '{tempTableName}'"; //Make sure that we can create and drop tables as the normal user but cannot do the same thing via Reports.GetTable(). //First, make sure that the regular user works as intended. DataCore.NonQ(tempTableDropQuery); DataCore.NonQ(tempTableCreateQuery); Assert.AreEqual(1, DataCore.GetTable(tempTableShowQuery).Rows.Count, "Root user was not able to create a new table."); DataCore.NonQ(tempTableDropQuery); //Next, make sure that user low cannot create the new table. Required to use the Middle Tier otherwise user low is ignored. DataAction.RunMiddleTierMock(() => { //User low should be able to run SELECT and SHOW commands. if (Reports.GetTable(tempTableShowQuery).Rows.Count != 0) //Should have been dropped via root user above. { throw new ApplicationException("Temporary table was not dropped correctly."); } //Reports.GetTable() should throw an exception due to the lack of the CREATE permission. Swallow it. ODException.SwallowAnyException(() => Reports.GetTable(tempTableCreateQuery)); //User low should not have been able to create the table. if (Reports.GetTable(tempTableShowQuery).Rows.Count != 0) { throw new ApplicationException("User low was able to create a table."); } }); }); thread.AddExceptionHandler(e => { ex = e; }); //This will cause the unit test to fail. thread.Name = "thread" + MethodBase.GetCurrentMethod().Name; thread.Start(); thread.Join(Timeout.Infinite); Assert.IsNull(ex, ex?.Message); }
///<summary>Fires a MiddleTierConnectionEvent of type MiddleTierConnectionLost to notify the main thread that the Middle Tier connection has been lost. ///Wait here until the connection is restored.</summary> private static void RemoteConnectionFailed() { RemotingClient.HasMiddleTierConnectionFailed = true; //Inform all threads that we've lost the MiddleTier connection, so they can handle this appropriately. MiddleTierConnectionEvent.Fire(new MiddleTierConnectionEventArgs(false)); //Keep the current thread stuck here while automatically retrying the connection up until the timeout specified. DateTime beginning = DateTime.Now; ODThread threadRetry = new ODThread(500, (o) => { if (!HasMiddleTierConnectionFailed) { o.QuitAsync(); return; } if ((DateTime.Now - beginning).TotalSeconds >= TimeSpan.FromHours(4).TotalSeconds) { return; //We have reached or exceeded the timeout. Stop automatically retrying and leave it up to a manual retry from the user. } try { if (IsMiddleTierAvailable()) { //Unset HasMiddleTierConnectionFailed flag allowing any blocked Middle Tier communication to continue. RemotingClient.HasMiddleTierConnectionFailed = false; //Also fire a DataConnectionEvent letting everyone who cares know that the connection has been restored. MiddleTierConnectionEvent.Fire(new MiddleTierConnectionEventArgs(true)); o.QuitAsync(); } } catch (Exception ex) { ex.DoNothing(); //Connection has not been restored yet. Wait a little bit and then try again. } }); threadRetry.Name = "MiddleTierConnectionLostAutoRetryThread"; threadRetry.AddExceptionHandler((e) => e.DoNothing()); threadRetry.Start(); //Wait here until the retry thread has finished which is either due to connection being restored or the timeout was reached. threadRetry.Join(Timeout.Infinite); //Wait forever because the retry thread has a timeout within itself. }
///<summary>Only call this method from SendPushBackground() or SendPushAlert(). See summary of those methods for documentation. ///If runAsync==true then spawns a worker thread and makes the web call. This method is passive and returns void so no reason to wait for return.</summary> private static void SendPush(PushType pushType, bool isAlert, long mobileAppDeviceNum = 0, long clinicNum = 0, long userNum = 0, List <long> listPrimaryKeys = null, List <string> listTags = null, string alertTitle = null, string alertMessage = null, bool runAsync = true) { void execute() { eServiceCode eService = eServiceCode.EClipboard; switch (pushType) { case PushType.CI_CheckinPatient: case PushType.CI_AddSheet: case PushType.CI_RemoveSheet: case PushType.CI_GoToCheckin: case PushType.CI_NewEClipboardPrefs: case PushType.CI_IsAllowedChanged: case PushType.CI_TreatmentPlan: case PushType.CI_RemoveTreatmentPlan: eService = eServiceCode.EClipboard; break; case PushType.ODM_NewTextMessage: case PushType.ODM_LogoutODUser: eService = eServiceCode.MobileWeb; break; case PushType.None: default: throw new Exception("Unsupported PushType: " + pushType.ToString()); } PushNotificationPayload payload = new PushNotificationPayload { IsAlert = isAlert, AlertMessage = alertMessage ?? "", AlertTitle = alertTitle ?? "", UserNum = userNum, PushNotificationActionJSON = JsonConvert.SerializeObject(new PushNotificationAction() { TypeOfPush = pushType, ListPrimaryKeys = listPrimaryKeys ?? new List <long>(), ListTags = listTags ?? new List <string>() }, typeof(PushNotificationAction), new JsonSerializerSettings()) }; if (mobileAppDeviceNum > 0) //Send to one exact device. { MobileAppDevice mad = MobileAppDevices.GetOne(mobileAppDeviceNum); if (mad == null) { throw new Exception("MobileAppDeviceNum not found: " + mobileAppDeviceNum.ToString()); } payload.DeviceId = mad.UniqueID; payload.ClinicNum = mad.ClinicNum; } else { payload.ClinicNum = clinicNum; } //Validate that this clinic is signed up for eClipboard if the push is related to eClipboard if (eService == eServiceCode.EClipboard && !MobileAppDevices.IsClinicSignedUpForEClipboard(payload.ClinicNum)) { throw new Exception($"ClinicNum {payload.ClinicNum} is not signed up for eClipboard."); } //Validate that this clinic is signed up for MobileWeb if the push is related to ODMobile else if (eService == eServiceCode.MobileWeb && !MobileAppDevices.IsClinicSignedUpForMobileWeb(payload.ClinicNum)) { if (clinicNum > -1 || pushType != PushType.ODM_LogoutODUser) //Logout is allowed to be sent to non-specific clinicNum. All others are not. { throw new Exception($"ClinicNum {payload.ClinicNum} is not signed up for ODMobile."); } } string jsonPayload = JsonConvert.SerializeObject(payload, typeof(PushNotificationPayload), new JsonSerializerSettings()); string result = WebServiceMainHQProxy.GetWebServiceMainHQInstance().SendPushNotification(PayloadHelper.CreatePayload("", eService), jsonPayload); if (result.ToLower() != "success") { throw new Exception(result); } } ODThread th = new ODThread(new ODThread.WorkerDelegate((o) => { execute(); })); th.AddExceptionHandler((e) => { if (MockExceptionHandler != null) { MockExceptionHandler(e); } else { Logger.WriteException(e, "PushNotifications"); } }); th.Name = "SendPush_" + pushType.ToString() + "_ClinicNum_" + clinicNum.ToString() + "_UserNum_" + userNum.ToString(); th.Start(); if (MockExceptionHandler != null || !runAsync) //Join back to main thread to cause this to be a blocking call. Unit tests will always block. { th.Join(Timeout.Infinite); } }
public static List <FeatureRequest> GetAll() { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { return(Meth.GetObject <List <FeatureRequest> >(MethodBase.GetCurrentMethod())); } //Create an ODThread so that we can safely change the database connection settings without affecting the calling method's connection. ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => { //Always set the thread static database connection variables to set the serviceshq db conn. #if DEBUG new DataConnection().SetDbT("localhost", "bugs", "root", "", "", "", DatabaseType.MySql, true); #else new DataConnection().SetDbT("server", "bugs", "root", "", "", "", DatabaseType.MySql, true); #endif #region WebServiceCustomerUpdates.FeatureRequestGetList string command = "SELECT request.RequestId,Approval,Description,Difficulty," + "vote.AmountPledged,IFNULL(vote.Points,0) AS points,vote.IsCritical,request.PatNum," + "TotalCritical,TotalPledged,TotalPoints,Weight " + "FROM request " + "LEFT JOIN vote ON vote.PatNum=1486 AND vote.RequestId=request.RequestId " + "WHERE (Approval=" + POut.Int((int)ApprovalEnum.New) + " " + "OR Approval=" + POut.Int((int)ApprovalEnum.Approved) + " " + "OR Approval=" + POut.Int((int)ApprovalEnum.InProgress) + " " + "OR Approval=" + POut.Int((int)ApprovalEnum.Complete) + ") " + "ORDER BY Approval, Weight DESC, points DESC"; DataTable raw = Db.GetTable(command); DataRow row; DataTable table = new DataTable(); table.TableName = "Table"; table.Columns.Add("approval"); table.Columns.Add("Description"); table.Columns.Add("Difficulty"); table.Columns.Add("isMine"); table.Columns.Add("myVotes"); table.Columns.Add("RequestId"); table.Columns.Add("totalVotes"); table.Columns.Add("Weight"); table.Columns.Add("personalVotes"); table.Columns.Add("personalCrit"); table.Columns.Add("personalPledged"); double myPledge; bool myCritical; double totalPledged; int totalCritical; for (int i = 0; i < raw.Rows.Count; i++) { row = table.NewRow(); row["RequestId"] = raw.Rows[i]["RequestId"].ToString(); //myVotes,myCritical,myPledge------------------------------------------------------ row["myVotes"] = raw.Rows[i]["Points"].ToString(); row["personalVotes"] = raw.Rows[i]["Points"].ToString(); if (row["myVotes"].ToString() == "0") { row["myVotes"] = ""; } myCritical = PIn.Bool(raw.Rows[i]["IsCritical"].ToString()); if (myCritical == true) { row["personalCrit"] = "1"; if (row["myVotes"].ToString() != "") { row["myVotes"] += "\r\n"; } row["myVotes"] += "Critical"; } else { row["personalCrit"] = "0"; } myPledge = PIn.Double(raw.Rows[i]["AmountPledged"].ToString()); if (myPledge != 0) { if (row["myVotes"].ToString() != "") { row["myVotes"] += "\r\n"; } row["myVotes"] += myPledge.ToString("c0"); row["personalPledged"] = myPledge.ToString(); } else { row["personalPledged"] = "0"; } //TotalPoints,TotalCritical,TotalPledged----------------------------------------------- row["totalVotes"] = raw.Rows[i]["TotalPoints"].ToString(); if (row["totalVotes"].ToString() == "0") { row["totalVotes"] = ""; } totalCritical = PIn.Int(raw.Rows[i]["TotalCritical"].ToString()); if (totalCritical != 0) { if (row["totalVotes"].ToString() != "") { row["totalVotes"] += "\r\n"; } row["totalVotes"] += "Critical:" + totalCritical.ToString(); } totalPledged = PIn.Double(raw.Rows[i]["TotalPledged"].ToString()); if (totalPledged != 0) { if (row["totalVotes"].ToString() != "") { row["totalVotes"] += "\r\n"; } row["totalVotes"] += totalPledged.ToString("c0"); } //end row["approval"] = ((ApprovalEnum)PIn.Int(raw.Rows[i]["Approval"].ToString())).ToString(); if (raw.Rows[i]["PatNum"].ToString() == "1486") { row["isMine"] = "X"; } else { row["isMine"] = ""; } row["Difficulty"] = raw.Rows[i]["Difficulty"].ToString(); row["Description"] = raw.Rows[i]["Description"].ToString(); row["Weight"] = raw.Rows[i]["Weight"].ToString(); table.Rows.Add(row); } o.Tag = table; #endregion })); odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { })); //Do nothing odThread.Name = "featureMarkAsInProgressThread"; odThread.Start(true); if (!odThread.Join(2000)) //Give this thread up to 2 seconds to complete. { return(new List <FeatureRequest>()); } DataTable tableRequests = (DataTable)odThread.Tag; List <FeatureRequest> listFeatureRequests = new List <FeatureRequest>(); foreach (DataRow dataRow in tableRequests.Rows) { FeatureRequest req = new FeatureRequest(); #region Convert DataTable Into FeatureRequest long.TryParse(dataRow["RequestId"].ToString(), out req.FeatReqNum); string[] votes = dataRow["totalVotes"].ToString().Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); string vote = votes.FirstOrDefault(x => !x.StartsWith("Critical") && !x.StartsWith("$")); if (!string.IsNullOrEmpty(vote)) { long.TryParse(vote, out req.Votes); } vote = votes.FirstOrDefault(x => x.StartsWith("Critical")); if (!string.IsNullOrEmpty(vote)) { long.TryParse(vote, out req.Critical); } vote = votes.FirstOrDefault(x => x.StartsWith("$")); if (!string.IsNullOrEmpty(vote)) { float.TryParse(vote, out req.Pledge); } req.Difficulty = PIn.Long(dataRow["Difficulty"].ToString()); req.Weight = PIn.Float(dataRow["Weight"].ToString()); req.Approval = dataRow["Weight"].ToString(); req.Description = dataRow["Description"].ToString(); #endregion listFeatureRequests.Add(req); } return(listFeatureRequests); }