using System; using System.Threading; using System.Collections; using System.Data.Odbc; namespace Server.Engines.MyRunUO { public class DatabaseCommandQueue { private Queue m_Queue; private ManualResetEvent m_Sync; private Thread m_Thread; private string m_CompletionString; private string m_ConnectionString; public bool HasCompleted { get; private set; } public void Enqueue( object obj ) { lock ( m_Queue.SyncRoot ) { m_Queue.Enqueue( obj ); try{ m_Sync.Set(); } catch{} } } 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(); } 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(); } } } } }