private static void DoRedeliveryIfRequiredLocked(ReplayConfiguration config, SafetyNetInfoCache snCache, SafetyNetInfoHashTable safetyNetInfos) { foreach (KeyValuePair <SafetyNetRequestKey, SafetyNetInfo> request in safetyNetInfos) { SafetyNetRedelivery.ProcessSingleRequest(config, snCache, request); } }
public static void MarkRedeliveryRequired(ReplayConfiguration configuration, DateTime failoverTimeUtc, DateTime startTimeUtc, DateTime endTimeUtc, long lastLogGenBeforeActivation, long numLogsLost) { SafetyNetRedelivery.Tracer.TraceDebug(0L, "MarkRedeliveryRequired() for {0}({1}) called: failoverTimeUtc={2}, startTimeUtc={3}, endTimeUtc={4}, lastLogGenBeforeActivation={5}, numLogsLost={6}", new object[] { configuration.Name, configuration.Identity, failoverTimeUtc, startTimeUtc, endTimeUtc, lastLogGenBeforeActivation, numLogsLost }); if (endTimeUtc < startTimeUtc) { SafetyNetRedelivery.Tracer.TraceError <string, string>(0L, "MarkRedeliveryRequired() for {0}({1}) failed because endTimeUtc should not be less than startTimeUtc", configuration.Name, configuration.Identity); DiagCore.AssertOrWatson(false, "endTimeUtc ({0}) should not be less than startTimeUtc ({1}) !", new object[] { endTimeUtc, startTimeUtc }); throw new DumpsterInvalidResubmitRequestException(configuration.DatabaseName); } TimeSpan timeSpan = endTimeUtc.Subtract(startTimeUtc); TimeSpan timeSpan2 = TimeSpan.FromSeconds((double)RegistryParameters.DumpsterRedeliveryMaxTimeRangeInSecs); if (timeSpan > timeSpan2) { SafetyNetRedelivery.Tracer.TraceError(0L, "MarkRedeliveryRequired() for {0}({1}) failed because the request window ({2}) is larger than the maximum allowed of {3}", new object[] { configuration.Name, configuration.Identity, timeSpan, timeSpan2 }); throw new DumpsterInvalidResubmitRequestException(configuration.DatabaseName); } string text; ActiveManagerCore.GetDatabaseMountStatus(configuration.IdentityGuid, out text); SafetyNetInfo safetyNetInfo = new SafetyNetInfo(text, lastLogGenBeforeActivation, numLogsLost, failoverTimeUtc, startTimeUtc, endTimeUtc); SafetyNetInfoCache safetyNetTable = configuration.ReplayState.GetSafetyNetTable(); safetyNetTable.Update(safetyNetInfo); ReplayEventLogConstants.Tuple_DatabaseDumpsterRedeliveryRequired.LogEvent(null, new object[] { configuration.DatabaseName, startTimeUtc, endTimeUtc }); ReplayCrimsonEvents.DumpsterRedeliveryRequired.Log <string, Guid, string, long, long, DateTime, DateTime, DateTime, bool, bool>(configuration.DatabaseName, configuration.IdentityGuid, text, lastLogGenBeforeActivation, numLogsLost, failoverTimeUtc, startTimeUtc, endTimeUtc, false, true); }
public static bool IsRedeliveryRequired(ReplayConfiguration replayConfig) { SafetyNetInfoCache safetyNetTable = replayConfig.ReplayState.GetSafetyNetTable(); return(safetyNetTable.IsRedeliveryRequired(true, true)); }
private static void ProcessSingleRequest(ReplayConfiguration config, SafetyNetInfoCache snCache, KeyValuePair <SafetyNetRequestKey, SafetyNetInfo> request) { SafetyNetRequestKey key = request.Key; SafetyNetInfo value = request.Value; string serverName = key.ServerName; DateTime requestCreationTimeUtc = key.RequestCreationTimeUtc; TimeSpan timeSpan = TimeSpan.FromSeconds((double)RegistryParameters.DumpsterRedeliveryExpirationDurationInSecs); if (requestCreationTimeUtc.Add(timeSpan) < DateTime.UtcNow) { SafetyNetRedelivery.Tracer.TraceDebug((long)config.GetHashCode(), "ProcessSingleRequest: Deleting Dumpster Redelivery request ({2}) for {0}({1}) because it is older than the maximum time for retries ({3}). CreationTimeUtc={4}", new object[] { config.Name, config.Identity, key, timeSpan, requestCreationTimeUtc }); ReplayCrimsonEvents.DumpsterRedeliverySpecificRequestExpired.Log <string, Guid, bool, DateTime, SafetyNetRequestKey, string, TimeSpan, bool>(config.DatabaseName, config.IdentityGuid, false, requestCreationTimeUtc, key, value.GetSerializedForm(), timeSpan, value.RedeliveryRequired); snCache.Delete(value); return; } if (!value.IsVersionCompatible()) { SafetyNetRedelivery.Tracer.TraceDebug((long)config.GetHashCode(), "ProcessSingleRequest: Skipping Dumpster Redelivery request ({2}) for {0}({1}) because it is of an incompatible version. ServerVersion={3}; RequestVersion={4}", new object[] { config.Name, config.Identity, key, SafetyNetInfo.VersionNumber, value.Version }); ReplayCrimsonEvents.DumpsterRedeliveryRequestVersionIncompatible.LogPeriodic <string, Guid, bool, DateTime, SafetyNetRequestKey, string, bool, Version, Version>(config.Identity + key.ToString(), DateTimeHelper.OneDay, config.DatabaseName, config.IdentityGuid, false, requestCreationTimeUtc, key, value.GetSerializedForm(), value.RedeliveryRequired, SafetyNetInfo.VersionNumber, value.Version); return; } if (!value.RedeliveryRequired) { SafetyNetRedelivery.Tracer.TraceDebug <string, string, SafetyNetRequestKey>((long)config.GetHashCode(), "ProcessSingleRequest: Skipping and deleting request ({2}) for {0}({1}) because RedeliveryRequired is 'false'.", config.Name, config.Identity, key); snCache.Delete(value); return; } if (value.RequestNextDueTimeUtc > DateTime.UtcNow) { SafetyNetRedelivery.Tracer.TraceDebug((long)config.GetHashCode(), "ProcessSingleRequest: Skipped processing redelivery request ({2}) for {0}({1}) due to backoff logic. The request will next run at '{3}'", new object[] { config.Name, config.Identity, key, value.RequestNextDueTimeUtc }); return; } SafetyNetRedelivery.Tracer.TraceDebug <string, string, SafetyNetRequestKey>((long)config.GetHashCode(), "ProcessSingleRequest: Processing redelivery request ({2}) for {0}({1})", config.Name, config.Identity, key); bool flag = true; DateTime startTimeUtc = value.StartTimeUtc; DateTime endTimeUtc = value.EndTimeUtc; List <string> list = null; List <string> list2 = null; TimeSpan value2 = TimeSpan.FromSeconds((double)RegistryParameters.DumpsterRedeliveryPrimaryRetryDurationInSecs); IMonitoringADConfig config2 = Dependencies.MonitoringADConfigProvider.GetConfig(true); if (value.HubServers == null || value.HubServers.Count == 0) { if (config2.ServerRole != MonitoringServerRole.DagMember) { SafetyNetRedelivery.LogSpecificRequestFailedEvent(config, key, value, "Local server is not a member of a DAG.", new object[0]); return; } List <IADServer> servers = config2.Servers; if (servers == null || servers.Count == 0) { SafetyNetRedelivery.LogSpecificRequestFailedEvent(config, key, value, "Could not find any BackEnd servers in local DAG '{0}'.", new object[] { config2.Dag.Name }); return; } list = new List <string>(servers.Count <IADServer>()); foreach (IADServer iadserver in servers) { list.Add(iadserver.Fqdn); } value.HubServers = list; } else if (requestCreationTimeUtc.Add(value2) >= DateTime.UtcNow) { list = value.PrimaryHubServers; } else { list = value.ShadowHubServers; flag = false; if (value.ShadowRequestCreateTimeUtc == DateTime.MinValue) { value.ShadowRequestCreateTimeUtc = DateTime.UtcNow; } } if (list == null || list.Count == 0) { list = value.HubServers; } if (SafetyNetRedelivery.Tracer.IsTraceEnabled(TraceType.DebugTrace)) { string text = string.Join(",", list); if (flag) { SafetyNetRedelivery.Tracer.TraceDebug((long)config.GetHashCode(), "ProcessSingleRequest: Processing redelivery request ({2}) for {0}({1}) : Primary phase. Servers={3}", new object[] { config.Name, config.Identity, key, text }); } else { SafetyNetRedelivery.Tracer.TraceDebug((long)config.GetHashCode(), "ProcessSingleRequest: Processing redelivery request ({2}) for {0}({1}) : Shadow copy phase. Servers={3}", new object[] { config.Name, config.Identity, key, text }); } } list2 = new List <string>(list.Count); value.RequestLastAttemptedTimeUtc = DateTime.UtcNow; foreach (string text2 in list) { Exception ex = SafetyNetRedelivery.DumpsterResubmitRpc(text2, config, key, value, config2, flag); if (ex != null) { list2.Add(text2); } } if (list2.Count == 0) { SafetyNetRedelivery.Tracer.TraceDebug <string, string, SafetyNetRequestKey>((long)config.GetHashCode(), "ProcessSingleRequest: Deleting dumpster request ({2}) for {0}({1}), since RPC has completed to all HUB servers", config.Name, config.Identity, key); value.RedeliveryRequired = false; value.RequestCompletedTimeUtc = DateTime.UtcNow; value.RequestNextDueTimeUtc = DateTime.MinValue; } else { value.RequestNextDueTimeUtc = SafetyNetRequestBackoff.GetNextDueTime(key, value, flag); SafetyNetRedelivery.Tracer.TraceDebug((long)config.GetHashCode(), "ProcessSingleRequest: Dumpster request ({2}) for {0}({1}): Setting next due time to {3}.", new object[] { config.Name, config.Identity, key, value.RequestNextDueTimeUtc }); ReplayCrimsonEvents.DumpsterRedeliveryRequestNextDueAt.Log <string, Guid, DateTime, DateTime, DateTime, DateTime>(config.DatabaseName, config.IdentityGuid, key.RequestCreationTimeUtc, value.StartTimeUtc, value.EndTimeUtc, value.RequestNextDueTimeUtc); } if (flag) { value.PrimaryHubServers = list2; } else { value.ShadowHubServers = list2; } if (value.RedeliveryRequired) { snCache.Update(value); return; } snCache.Delete(value); }
public static void DoRedeliveryIfRequired(object replayConfig) { ReplayConfiguration replayConfiguration = replayConfig as ReplayConfiguration; SafetyNetRedelivery.Tracer.TraceDebug <string, string>(0L, "DumpsterRedeliveryManager: DoRedeliveryIfRequired for {0}({1}).", replayConfiguration.Name, replayConfiguration.Identity); if (replayConfiguration == null) { SafetyNetRedelivery.Tracer.TraceError(0L, "DoRedeliveryIfRequired: Invalid ReplayConfiguration object passed in."); return; } Exception ex = null; bool flag = false; try { SafetyNetInfoCache safetyNetTable = replayConfiguration.ReplayState.GetSafetyNetTable(); SafetyNetInfoHashTable safetyNetInfosReadThrough = safetyNetTable.GetSafetyNetInfosReadThrough(); if (!safetyNetInfosReadThrough.RedeliveryRequired) { SafetyNetRedelivery.Tracer.TraceDebug <string, string>((long)replayConfiguration.GetHashCode(), "DoRedeliveryIfRequired: Skipping Redelivery for {0}({1}) because RedeliveryRequired is 'false'.", replayConfiguration.Name, replayConfiguration.Identity); } else { flag = SafetyNetRedelivery.TryEnterLock(replayConfiguration); if (!flag) { SafetyNetRedelivery.Tracer.TraceDebug <string, string>((long)replayConfiguration.GetHashCode(), "DoRedeliveryIfRequired: Another thread is doing Redelivery on {0}({1})", replayConfiguration.Name, replayConfiguration.Identity); } else { SafetyNetRedelivery.Tracer.TraceDebug <string, string>((long)replayConfiguration.GetHashCode(), "DoRedeliveryIfRequired: Processing dumpster re-delivery for instance {0}({1})", replayConfiguration.Name, replayConfiguration.Identity); SafetyNetRedelivery.DoRedeliveryIfRequiredLocked(replayConfiguration, safetyNetTable, safetyNetInfosReadThrough); } } } catch (DumpsterRedeliveryException ex2) { ex = ex2; } catch (MonitoringADConfigException ex3) { ex = ex3; } catch (ClusterException ex4) { ex = ex4; } catch (TransientException ex5) { ex = ex5; } catch (IOException ex6) { ex = ex6; } finally { if (ex != null) { SafetyNetRedelivery.Tracer.TraceError <string, string, Exception>((long)replayConfiguration.GetHashCode(), "DoRedeliveryIfRequired() for {0}({1}) failed with Exception: {2}", replayConfiguration.Name, replayConfiguration.Identity, ex); ReplayCrimsonEvents.DumpsterRedeliveryForDatabaseFailed.LogPeriodic <string, Guid, bool, string, Exception>(replayConfiguration.Identity, DiagCore.DefaultEventSuppressionInterval, replayConfiguration.DatabaseName, replayConfiguration.IdentityGuid, false, ex.Message, ex); ReplayEventLogConstants.Tuple_DumpsterRedeliveryFailed.LogEvent(replayConfiguration.Identity, new object[] { ex.Message, replayConfiguration.Name }); } if (flag) { SafetyNetRedelivery.ExitLock(replayConfiguration); } } }