protected override bool Run(object parameters) { #if DEBUG Shared.EventLog.Debug("RepThread " + System.Reflection.MethodBase.GetCurrentMethod().Name); #endif DatabaseConnection connection = (DatabaseConnection)parameters; bool tableUpdated = false; TimeSpan ts = new TimeSpan(0, 2, 0); if (!_IsRunning && (DateTime.Now - _lastCheckUpdates) >= ts) { try { _lastCheckUpdates = DateTime.Now; // are we looking for remote updates to the database if (connection.RemoteUpdate) { AddToLogFile(String.Format("{0} Checking Version", ConnectionName)); API api = new API(); try { DatabaseRemoteUpdate remoteUpdate = new DatabaseRemoteUpdate(); try { remoteUpdate.OnNewMessage += DatabaseRemoteUpdate_OnNewMessage; int version = Version; if (remoteUpdate.CheckForDatabaseUpdates(connection.Name, connection.ChildDatabase, connection.RemoteUpdateXML, connection.RemoteUpdateLocation, ref version, ref tableUpdated)) { Version = version; if (api.UpdateCurrentDatabaseVersion(connection, version)) { string fileName = String.Empty; if (connection.ReplicateDatabase && connection.ReplicateUpdateTriggers && tableUpdated) { if (connection.ReplicationType == ReplicationType.Child) { //create replication triggers if needed and new database users ReplicationPrepareChildDatabase repEng = new ReplicationPrepareChildDatabase(); try { if (tableUpdated) { AddToLogFile(String.Format("{0} Rebuilding Child Replication Triggers", ConnectionName)); } if (repEng.PrepareDatabaseForReplication(_databaseConnection.ChildDatabase, tableUpdated, false, ref fileName, remoteUpdate)) { AddToLogFile(String.Format("{0} Replication Child Triggers Rebuilt", ConnectionName)); } } finally { repEng = null; } } else if (connection.ReplicationType == ReplicationType.Master) { //create replication triggers if needed and new database users ReplicationPrepareMasterDatabase repEng = new ReplicationPrepareMasterDatabase(); try { if (tableUpdated) { AddToLogFile(String.Format("{0} Rebuilding Master Replication Triggers", ConnectionName)); } if (repEng.PrepareDatabaseForReplication(_databaseConnection.ChildDatabase, tableUpdated, false, ref fileName, remoteUpdate)) { AddToLogFile(String.Format("{0} Replication Master Triggers Rebuilt", ConnectionName)); } } finally { repEng = null; } } } } } } finally { remoteUpdate.OnNewMessage -= DatabaseRemoteUpdate_OnNewMessage; remoteUpdate = null; } } finally { api = null; } } // are we backing up the database if (connection.BackupDatabase) { DateTime compare = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, connection.BackupAfterTime.Hour, connection.BackupAfterTime.Minute, 0); TimeSpan spanLastBackup = DateTime.Now - connection.LastBackupTime; if ( ( (!connection.BackupAfterTimeEnabled || (connection.BackupAfterTimeEnabled && DateTime.Now.Subtract(compare).TotalMinutes >= 0) ) || (spanLastBackup.TotalDays >= 1.0) )) { AddToLogFile(String.Format("{0} Checking Backup", ConnectionName)); CheckLatestDBBackup(); } else { } } } catch (Exception errUB) { Shared.EventLog.Add(errUB); } } int missingRecordCount = 0; try { if (CanReplicate && connection.ReplicationType == ReplicationType.Child) { ts = new TimeSpan(0, _runInterval, 0); // xx minute increments // has it been xx minutes since last run? if (!_IsRunning && (DateTime.Now - LastRunReplication) >= ts) { AddToLogFile(String.Format("Run Replication {0}", ConnectionName)); _IsRunning = true; //properties _replicationEngine = new ReplicationEngine( ConnectionName, _databaseConnection.ReplicateDatabase, _databaseConnection.ChildDatabase, _databaseConnection.MasterDatabase); try { _replicationEngine.Validate = true; // settings _replicationEngine.VerifyAllDataInterval = (int)_databaseConnection.VerifyDataInterval; _replicationEngine.VerifyTableCounts = 20; #if ERROR_LIMIT_30000 _replicationEngine.ForceRestartErrorCount = 30000; #else _replicationEngine.ForceRestartErrorCount = (int)_databaseConnection.VerifyErrorReset; #endif _replicationEngine.MaximumDownloadCount = (int)_databaseConnection.MaximumDownloadCount; _replicationEngine.MaximumUploadCount = (int)_databaseConnection.MaximumUploadCount; _replicationEngine.TimeOutMinutes = (int)_databaseConnection.TimeOut; _replicationEngine.RequireUniqueAccess = _databaseConnection.RequireUniqueAccess; // event hookups _replicationEngine.OnProgress += new ReplicationPercentEventArgs(rep_OnProgress); _replicationEngine.OnReplicationTextChanged += new ReplicationProgress(rep_OnReplicationTextChanged); _replicationEngine.BeginReplication += new ReplicationEventHandler(rep_BeginReplication); _replicationEngine.EndReplication += new ReplicationEventHandler(rep_EndReplication); _replicationEngine.OnReplicationError += new ReplicationError(rep_OnReplicationError); _replicationEngine.OnIDChanged += rep_OnIDChanged; _replicationEngine.OnCheckCancel += _replicationEngine_OnCheckCancel; //are we forcing hard confirm between certain hours? if (!ForceVerifyRecords) { ForceVerifyRecords = ForceConfirmBasedOnHoursOrIterations(); } _replicationError = _replicationEngine.Run(_allowConfirmCounts, ForceVerifyRecords); missingRecordCount = _replicationEngine.MissingRecordCount; switch (_replicationError) { case ReplicationResult.ThresholdExceeded: _runInterval = 0; break; case ReplicationResult.UniqueAccessDenied: // we do not reset force hard confirm here as it was set before the run //_forceHardConfirm = _forceHardConfirm; _runInterval = (int)_databaseConnection.ReplicateInterval; break; } if (ForceVerifyRecords && (missingRecordCount >= _databaseConnection.VerifyErrorReset)) { AddToLogFile(String.Format("{0} Force Verify Records Missing Records Exceeded", ConnectionName)); ForceVerifyRecords = true; _runInterval = 0; // get list of confirmed tables so we don't scan them next time //_confirmedTables = _replicationEngine.TablesConfirmedCorrect; } else { switch (_replicationError) { case ReplicationResult.TimeOutExceeded: //_confirmedTables = _replicationEngine.TablesConfirmedCorrect; _runInterval = (int)_databaseConnection.ReplicateInterval; AddToLogFile(String.Format("{0} Time out exceeded, restarting", ConnectionName)); break; case ReplicationResult.ThresholdExceeded: //_confirmedTables = _replicationEngine.TablesConfirmedCorrect; // we do not reset force hard confirm here as it was set before the run //_forceHardConfirm = _forceHardConfirm; _runInterval = 0; break; case ReplicationResult.UniqueAccessDenied: //_confirmedTables = _replicationEngine.TablesConfirmedCorrect; _runInterval = (int)_databaseConnection.ReplicateInterval; AddToLogFile(String.Format("{0} Unique access for deep scan not allowed, retry next time...", ConnectionName)); break; case ReplicationResult.Error: case ReplicationResult.DeepScanInitialised: //_confirmedTables = _replicationEngine.TablesConfirmedCorrect; _runInterval = 0; break; case ReplicationResult.NotInitialised: case ReplicationResult.Cancelled: case ReplicationResult.Completed: case ReplicationResult.DeepScanCompleted: ForceVerifyRecords = false; //_confirmedTables = String.Empty; _replicationEngine.Statuses.Clear(); _runInterval = (int)_databaseConnection.ReplicateInterval; break; } } } finally { _replicationEngine.Dispose(); _replicationEngine = null; } _IsRunning = false; LastRunReplication = DateTime.Now; _replicationCount++; //log management Shared.EventLog.ArchiveOldLogFiles(); } } TimeSpan t = LastRunReplication.AddMinutes(_runInterval) - DateTime.Now; SendToTCPClients(String.Format("Sleeping, time until next run {0}", t.ToString().Substring(0, 8))); } catch (Exception err) { Shared.EventLog.Add(err); _IsRunning = false; AddToLogFile(String.Format("{0} {1}", ConnectionName, err.Message)); AddToLogFile(err.StackTrace.ToString()); LastRunReplication = DateTime.Now; } finally { IndicateNotHanging(); } return(true); }
public SchemaValidation(DatabaseConnection connection) : base(connection, new TimeSpan()) { }