using System; using System.Collections.Generic; using System.Data; using System.Threading; using MySql.Data.MySqlClient; using DuckEmulator.HabboHotel.Inside.Storage.MySql.Database; using DuckEmulator.HabboHotel.Inside.Storage.MySql.Database.Exceptions; using DuckEmulator.HabboHotel.Inside.Storage.MySql.Database.Interfaces; namespace DuckEmulator.HabboHotel.Inside.Storage.MySql.Database { class DatabaseManager { #region Delegates public delegate void DatabaseEvent(DatabaseClient client); #endregion private int beginClientAmount; private string connectionString; private List databaseClients; private DatabaseEvent privateDbEvent; private bool isConnected; private uint maxPoolSize; private DatabaseServer server; public DatabaseManager(uint maxPoolSize, int clientAmount) { if (maxPoolSize < clientAmount) { throw new DatabaseException("The poolsize can not be larger than the client amount!"); } beginClientAmount = clientAmount; this.maxPoolSize = maxPoolSize; } public event DatabaseEvent dbEvent { add { DatabaseEvent event3; DatabaseEvent dbEvent = privateDbEvent; do { event3 = dbEvent; var event4 = (DatabaseEvent) Delegate.Combine(event3, value); dbEvent = Interlocked.CompareExchange(ref privateDbEvent, event4, event3); } while (dbEvent != event3); } remove { DatabaseEvent event3; DatabaseEvent dbEvent = privateDbEvent; do { event3 = dbEvent; var event4 = (DatabaseEvent) Delegate.Remove(event3, value); dbEvent = Interlocked.CompareExchange(ref privateDbEvent, event4, event3); } while (dbEvent != event3); } } private void addConnection(int id) { var item = new DatabaseClient(this, id); item.connect(); databaseClients.Add(item); } private void createNewConnectionString() { var _connectionString = new MySqlConnectionStringBuilder(); maxPoolSize = (uint) (maxPoolSize*1.5); _connectionString.Server = server.getHost(); _connectionString.Port = server.getPort(); _connectionString.UserID = server.getUsername(); _connectionString.Password = server.getPassword(); _connectionString.Database = server.getDatabaseName(); _connectionString.MinimumPoolSize = maxPoolSize/2; _connectionString.MaximumPoolSize = maxPoolSize; setConnectionString(_connectionString); } public void destroy() { lock (this) { isConnected = false; if (databaseClients != null) { foreach (DatabaseClient client in databaseClients) { if (!client.isAvailable()) { client.Dispose(); } client.disconnect(); } databaseClients.Clear(); } } } private void disconnectUnusedClients() { lock (this) { foreach (DatabaseClient client in databaseClients) { if (client.isAvailable()) { client.disconnect(); } } } } private DatabaseClient getClient(bool autoCommit) { lock (this) { for (int i = 0; i < databaseClients.Count; i++) { if (databaseClients[i].isAvailable()) { if (databaseClients[i].getConnectionState() == ConnectionState.Broken) { databaseClients[i].disconnect(); databaseClients[i] = new DatabaseClient(this, i); } if (databaseClients[i].getConnectionState() == ConnectionState.Closed) { databaseClients[i].connect(); } if (databaseClients[i].getConnectionState() == ConnectionState.Open) { databaseClients[i].prepare(autoCommit); return databaseClients[i]; } } } if (databaseClients.Count < maxPoolSize) { addConnection(databaseClients.Count); return getClient(autoCommit); } createNewConnectionString(); return getClient(autoCommit); } } internal string getConnectionString() { return connectionString; } public int getOpenConnectionCount() { int num = 0; lock (this) { foreach (DatabaseClient client in databaseClients) { if ((((client.getConnectionState() == ConnectionState.Open) || (client.getConnectionState() == ConnectionState.Fetching)) || (client.getConnectionState() == ConnectionState.Executing)) || (client.getConnectionState() == ConnectionState.Fetching)) { num++; } } } return num; } internal IQueryAdapter getQueryreactor() { return getQueryreactor(false); } internal IQueryAdapter getQueryreactor(bool transaction) { return getClient(transaction).getQueryReactor(); } public bool init() { try { DatabaseClient client; //Out.WriteLine("Creating new database connections.. stand by..", Out.logFlags.ImportantLogLevel); var _connectionString = new MySqlConnectionStringBuilder { Server = server.getHost(), Port = server.getPort(), UserID = server.getUsername(), Password = server.getPassword(), Database = server.getDatabaseName(), MinimumPoolSize = maxPoolSize / 2, MaximumPoolSize = maxPoolSize }; setConnectionString(_connectionString); databaseClients = new List((int) maxPoolSize); if (beginClientAmount != 0) { for (int i = 0; i < beginClientAmount; i++) { /*Out.WriteLine( string.Concat(new object[] { "Opening database connection [", i.ToString(), "] out of [", beginClientAmount, "]" }), Out.logFlags.lowLogLevel);*/ client = new DatabaseClient(this, i); if (privateDbEvent != null) { privateDbEvent(client); } client.connect(); databaseClients.Add(client); } } else { client = new DatabaseClient(this, -1); client.connect(); client.disconnect(); } } catch (MySqlException) { isConnected = false; //Out.writeError("Could not connect the clients to the database: " + exception.Message); return false; } //Out.WriteLine("Created new connections: [" + beginClientAmount + "]", Out.logFlags.ImportantLogLevel); isConnected = true; return true; } public bool isConnectedToDatabase() { return isConnected; } private void setConnectionString(MySqlConnectionStringBuilder _connectionString) { connectionString = _connectionString.ToString(); //Out.WriteLine(connectionString, Out.logFlags.lowLogLevel); } public bool setServerDetails(string host, uint port, string username, string password, string databaseName) { try { server = new DatabaseServer(host, port, username, password, databaseName); /*Out.WriteLine("Database connector succesfully set the connection details", Out.logFlags.ImportantLogLevel);*/ return true; } catch (DatabaseException) { isConnected = false; //Out.writeError("Database connector fialed to set the connection details: " + exception.Message); return false; } } } }