using System; using System.Data; using System.Collections; using System.Configuration; using System.Collections.Generic; using System.Collections.Specialized; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Threading; using System.Diagnostics; namespace WmData { public abstract class WmDataLinkPage : System.Web.UI.Page { protected WmGenericData data = null; protected WmDataLink dataLink = null; protected abstract void initDataLinkPage(); protected void Page_Load(object sender, EventArgs e) {} protected override void OnInit(EventArgs e) { base.OnInit(e); initDataLinkPage(); DataLinkCommand command = DataLinkCommand.STATUS; if (Request["command"] != null) { try { string commandText = Request["command"]; commandText = commandText.ToUpper(); command = (DataLinkCommand)Enum.Parse(typeof(DataLinkCommand), commandText); } catch { } } switch (command) { case DataLinkCommand.CURRENT_ROLE: handleCommandCurrentRole(); break; case DataLinkCommand.STATUS: handleCommandStatus(); break; case DataLinkCommand.LIST_SERVERS: handleCommandListServers(); break; case DataLinkCommand.GET_CHECKSUM: handleCommandGetChecksum(); break; case DataLinkCommand.GET_TRANSACTIONS: handleCommandGetTransactions(); break; case DataLinkCommand.GET_DATATABLE: handleCommandGetDataTable(); break; case DataLinkCommand.GET_CURRENT_MAXIMUM_ID: handleCommandGetCurrentMaximumId(); break; case DataLinkCommand.GET_ROW_COUNT: handleCommandGetRowCount(); break; case DataLinkCommand.LINK_HEALTH: handleCommandLinkHealth(); break; } } public void handleCommandLinkHealth() { // link ok if: // - active role // - backup role AND: // - all tables are OK // - if OUT OF SYNC and last transaction is less then 10 minutes old // bool isHealthy = false; string reason = ""; if (dataLink.CurrentRole == WmDataLinkRole.ACTIVE) { isHealthy = true; reason = "This is the active server."; } else if (dataLink.CurrentRole == WmDataLinkRole.BACKUP) { if (areSyncObjectTypesSynced()) { isHealthy = true; reason = "This server is entirely in sync."; } else { long fiveMinutesAgoInUtcTicks = DateTime.UtcNow.AddMinutes(-5).Ticks; if (dataLink.LastSyncMomentUtcTicks < fiveMinutesAgoInUtcTicks) { // if the last sync round is less then five minutes ago isHealthy = false; reason = "Last transaction was more than five minutes ago."; } else { isHealthy = true; reason = "Awaiting next sync round."; } } } else { isHealthy = false; reason = "This server is currently "+dataLink.CurrentRole.ToString()+"."; } string response = null; if (isHealthy) { response = "[HEALTHY] " + reason; } else { response = "[SICK] " + reason; } Response.Write(response); } public void handleCommandCurrentRole() { Response.Write(dataLink.CurrentRole.ToString()); } public void handleCommandListServers() { foreach (WmDataLinkServer server in dataLink.DataLinkServers) { Response.Write(server.ServerUrl + Environment.NewLine); } } public void handleCommandGetChecksum() { string dataTableName = ""; if (Request["table"] != null) { dataTableName = Request["table"]; } Response.Write(data.getChecksum(dataTableName)); } public void handleCommandGetCurrentMaximumId() { string dataTableName = ""; if (Request["table"] != null) { dataTableName = Request["table"]; } Response.Write(data.getCurrentMaximumId(dataTableName)); } public void handleCommandGetRowCount() { string dataTableName = ""; if (Request["table"] != null) { dataTableName = Request["table"]; } WmIntermediateObject intermediateObject =data.IntermediateObjectManager.getExistingIntermediateObjectByTableName(dataTableName); if (intermediateObject != null) { Type objectType = intermediateObject.ObjectType; Response.Write(data.getRowCount(objectType)); } else { Response.Write("0"); } } public void handleCommandGetTransactions() { long sinceUtcTicks = 0; if (Request["since"] != null) { try { sinceUtcTicks = long.Parse(Request["since"]); } catch { } } string transactionsAsXml = dataLink.getTransactionsAsXmlSince(sinceUtcTicks); transactionsAsXml = WmDataTools.compress(transactionsAsXml); Response.Write(transactionsAsXml); } public void handleCommandGetDataTable() { string dataTableName = ""; if (Request["table"] != null) { dataTableName = Request["table"]; } WmIntermediateObject intermediateObject = data.IntermediateObjectManager.getExistingIntermediateObjectByTableName(dataTableName); if (intermediateObject == null) { throw new NullReferenceException("WmDataTransactionManager: Attempt to import object that is unknown at the Intermediate Object Manager, try to issue a local get select call first"); } string dataTableAsXml = dataLink.getDataTableAsXml(intermediateObject.ObjectType); dataTableAsXml = WmDataTools.compress(dataTableAsXml); Response.Write(dataTableAsXml); } protected bool areSyncObjectTypesSynced() { bool inSync = false; WmDataLinkServer activeServer = dataLink.getActiveServer(); if (activeServer != null) { inSync = true; List syncObjectTypes = data.DataLink.SyncObjectTypes; foreach (Type syncObjectType in syncObjectTypes) { string syncObjectTableName = WmDataTools.getTableName(syncObjectType); string localChecksum = data.getChecksum(syncObjectTableName).ToString(); string remoteChecksum = activeServer.getChecksum(syncObjectTableName).ToString(); if (!remoteChecksum.Equals(localChecksum)) { inSync = false; break; // does not make sense to look further, we're out of sync. } } } return inSync; } public void handleCommandStatus() { WmDataLinkServer activeServer = dataLink.getActiveServer(); string activeServerDisplayName = "none"; if (activeServer != null) { activeServerDisplayName = activeServer.ServerUrl; } Response.Write("
");
            Response.Write("WmDataLink v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version+" - (c) W.L. Middelkoop" +Environment.NewLine);
            Response.Write("Data engine in use:     " + data.GetType().Name + Environment.NewLine);
            Response.Write("Active server:          " + activeServerDisplayName + Environment.NewLine);
            Response.Write("This server address:    " + dataLink.ThisServerAddress + Environment.NewLine);
            Response.Write("This server role:       " + dataLink.CurrentRole.ToString() + Environment.NewLine);
            
            DateTime lastSyncMoment = new DateTime(dataLink.Status.LastSyncMomentUtcTicks);
            TimeSpan delay = DateTime.UtcNow-lastSyncMoment;

            Response.Write("Last transaction (UTC): " + lastSyncMoment.ToString() + " (difference: " + delay.ToString() + ")" + Environment.NewLine);
            Response.Write(Environment.NewLine);
            Response.Write("The following object types are linked:"+Environment.NewLine);
            Response.Write(Environment.NewLine);
            int column1Width = 25;
            int column2Width = 19;
            int column3Width = 19;
            int column4Width = 8;
            int column5Width = 15;
            int column6Width = 15;
            int column7Width = 17;
            int column8Width = 17;
            int column9Width = 13;

            string heading1Text = WmDataTools.makeSureStringHasMinimumLength("OBJECTTYPE",column1Width,true);
            string heading2Text = WmDataTools.makeSureStringHasMinimumLength("LOCAL ROW COUNT",column2Width,false);
            string heading3Text = WmDataTools.makeSureStringHasMinimumLength("ACTIVE ROW COUNT", column3Width, false);
            string heading4Text = WmDataTools.makeSureStringHasMinimumLength("ROWS", column4Width, false);
            string heading5Text = WmDataTools.makeSureStringHasMinimumLength("LOCAL MAX ID",column5Width,false);
            string heading6Text = WmDataTools.makeSureStringHasMinimumLength("ACTIVE MAX ID", column6Width, false);
            string heading7Text = WmDataTools.makeSureStringHasMinimumLength("LOCAL CHECKSUM",column7Width,false);
            string heading8Text = WmDataTools.makeSureStringHasMinimumLength("ACTIVE CHECKSUM",column8Width,false);
            string heading9Text = WmDataTools.makeSureStringHasMinimumLength("CHECK", column9Width, false);
            
            Response.Write(heading1Text+heading2Text+heading3Text+heading4Text+heading5Text+heading6Text+heading7Text+heading8Text+ heading9Text+Environment.NewLine);

            List syncObjectTypes = data.DataLink.SyncObjectTypes;
            foreach (Type syncObjectType in syncObjectTypes) {
                string syncObjectTableName = WmDataTools.getTableName(syncObjectType);

                int localRowCount = data.getRowCount(syncObjectType);
                int remoteRowCount = 0;
                int remoteCurrentMaximumId = 0;

                string rowCountPercentageText = "-";
                string localChecksum = data.getChecksum(syncObjectTableName).ToString();
                string remoteChecksum = "n/a";
                string checkText = "-";

                if (activeServer != null) {
                    remoteRowCount = activeServer.getRowCount(syncObjectTableName);
                    remoteCurrentMaximumId = activeServer.getCurrentMaximumId(syncObjectTableName);
                    rowCountPercentageText = Math.Round(((double)localRowCount / remoteRowCount) * 100, 2).ToString(".0") + "%";
                    remoteChecksum = activeServer.getChecksum(syncObjectTableName).ToString();

                    if (remoteChecksum.Equals(localChecksum)) {
                        checkText = "OK";
                    } else {
                        checkText = "OUT OF SYNC";
                    }
                }

                string column1Text = WmDataTools.makeSureStringHasMinimumLength(syncObjectType.Name,column1Width,true);
                string column2Text = WmDataTools.makeSureStringHasMinimumLength(localRowCount.ToString(), column2Width, false);
                string column3Text = WmDataTools.makeSureStringHasMinimumLength(remoteRowCount.ToString(), column3Width, false);
                string column4Text = WmDataTools.makeSureStringHasMinimumLength(rowCountPercentageText, column4Width, false);
                
                string column5Text = WmDataTools.makeSureStringHasMinimumLength(data.getCurrentMaximumId(syncObjectTableName).ToString(), column5Width, false);
                string column6Text = WmDataTools.makeSureStringHasMinimumLength(remoteCurrentMaximumId.ToString(), column5Width, false);
                
                string column7Text = WmDataTools.makeSureStringHasMinimumLength(localChecksum, column7Width, false);
                string column8Text = WmDataTools.makeSureStringHasMinimumLength(remoteChecksum, column8Width, false);

                string column9Text = WmDataTools.makeSureStringHasMinimumLength(checkText, column9Width, false);

                Response.Write(column1Text + column2Text + column3Text + column4Text + column5Text +  column6Text+column7Text+column8Text+column9Text+ Environment.NewLine);
                

            }

            Response.Write("
"); } public WmGenericData Data { get { return data; } } } public enum DataLinkCommand { CURRENT_ROLE = 1, STATUS = 2, LIST_SERVERS = 10, GET_TRANSACTIONS = 20, GET_CHECKSUM = 30, GET_DATATABLE = 40, GET_CURRENT_MAXIMUM_ID = 50, GET_ROW_COUNT = 60, LINK_HEALTH = 70 } }