using System; using System.Collections; using System.Data.Odbc; using System.Threading; namespace Server.Engines.MyRunUO { public class DatabaseCommandQueue { private string m_CompletionString; private string m_ConnectionString; private Queue m_Queue; private ManualResetEvent m_Sync; private Thread m_Thread; public DatabaseCommandQueue(string completionString, string threadName) : this(Config.CompileConnectionString(), completionString, threadName) { } public DatabaseCommandQueue(string connectionString, string completionString, string threadName) { m_CompletionString = completionString; m_ConnectionString = connectionString; m_Queue = Queue.Synchronized(new Queue()); m_Queue.Enqueue(null); // signal connect /*m_Queue.Enqueue( "DELETE FROM myrunuo_characters" ); m_Queue.Enqueue( "DELETE FROM myrunuo_characters_layers" ); m_Queue.Enqueue( "DELETE FROM myrunuo_characters_skills" ); m_Queue.Enqueue( "DELETE FROM myrunuo_guilds" ); m_Queue.Enqueue( "DELETE FROM myrunuo_guilds_wars" );*/ m_Sync = new ManualResetEvent(true); m_Thread = new Thread(Thread_Start); m_Thread.Name = threadName; //"MyRunUO Database Command Queue"; m_Thread.Priority = Config.DatabaseThreadPriority; m_Thread.Start(); } public bool HasCompleted{ get; private set; } public void Enqueue(object obj) { lock (m_Queue.SyncRoot) { m_Queue.Enqueue(obj); try { m_Sync.Set(); } catch { } } } private void Thread_Start() { bool connected = false; OdbcConnection connection = null; OdbcCommand command = null; OdbcTransaction transact = null; DateTime start = DateTime.UtcNow; bool shouldWriteException = true; while (true) { m_Sync.WaitOne(); while (m_Queue.Count > 0) try { object obj = m_Queue.Dequeue(); if (obj == null) { if (connected) { if (transact != null) try { transact.Commit(); } catch (Exception commitException) { Console.WriteLine("MyRunUO: Exception caught when committing transaction"); Console.WriteLine(commitException); try { transact.Rollback(); Console.WriteLine("MyRunUO: Transaction has been rolled back"); } catch (Exception rollbackException) { Console.WriteLine("MyRunUO: Exception caught when rolling back transaction"); Console.WriteLine(rollbackException); } } try { connection.Close(); } catch { } try { connection.Dispose(); } catch { } try { command.Dispose(); } catch { } try { m_Sync.Close(); } catch { } Console.WriteLine(m_CompletionString, (DateTime.UtcNow - start).TotalSeconds); HasCompleted = true; return; } try { connected = true; connection = new OdbcConnection(m_ConnectionString); connection.Open(); command = connection.CreateCommand(); if (Config.UseTransactions) { transact = connection.BeginTransaction(); command.Transaction = transact; } } catch (Exception e) { try { transact?.Rollback(); } catch { } try { connection?.Close(); } catch { } try { connection?.Dispose(); } catch { } try { command?.Dispose(); } catch { } try { m_Sync.Close(); } catch { } Console.WriteLine("MyRunUO: Unable to connect to the database"); Console.WriteLine(e); HasCompleted = true; return; } } else if (obj is string s) { command.CommandText = s; command.ExecuteNonQuery(); } else { string[] parms = (string[])obj; command.CommandText = parms[0]; if (command.ExecuteScalar() == null) { command.CommandText = parms[1]; command.ExecuteNonQuery(); } } } catch (Exception e) { if (shouldWriteException) { Console.WriteLine("MyRunUO: Exception caught in database thread"); Console.WriteLine(e); shouldWriteException = false; } } lock (m_Queue.SyncRoot) { if (m_Queue.Count == 0) m_Sync.Reset(); } } } } }