/// <summary> /// initializes the connection string to the primary. /// </summary> private void InitializeConnectionToPrimary() { // if we don't have a hold on the primary yet... initialize the client if (this.self != null) { return; } this.self = this.getClientToPrimary(); }
/// <summary> /// Closes this scheduled command daemon /// </summary> internal void Close() { this.execution.Drain(HelperTypes.ExecutionQueue.DrainMode.DisallowAllFurtherEnqueues); lock (this.childrenProcessorLock) { this.nodesToProcess.Clear(); RingMasterServerInstrumentation.Instance.OnScheduledCommandQueueChange(this.nodesToProcess.Count); } this.self.Close(); this.self = null; }
/// <summary> /// ensures that the initial tree from configuration is initialized. /// This only happens on the primary, and only once after primary election. /// </summary> /// <param name="rm">the rm object to use</param> private void EnsureBaseTreeBuilt(AbstractRingMaster rm) { if (rm == null || !this.backend.IsPrimary()) { return; } try { string fromConfig = this.getSetting("RingMaster.InitialTree"); if (fromConfig == null || string.Equals(this.appliedFromConfig, fromConfig)) { return; } string[] elements = fromConfig.Split(new char[] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string elem in elements) { string el = elem; if (el.StartsWith("-")) { el = el.Substring(1); if (string.Equals(el, "/")) { Trace.TraceError("It is not allowed to cleanup the whole tree"); throw new InvalidOperationException("It is not allowed to cleanup the whole tree"); } IStat s = rm.Exists(el, false, false); if (s != null) { rm.Delete(el, s.Version, DeleteMode.CascadeDelete); Trace.TraceInformation("PseudoNodes.Init: Deleting " + el); } } else { rm.Create(el, null, null, CreateMode.PersistentAllowPathCreation); Trace.TraceInformation("PseudoNodes.Init: Creating " + el); } } this.appliedFromConfig = fromConfig; } catch (Exception) { // ignore } }
/// <summary> /// Initializes a new instance of the <see cref="ScheduledCommand"/> class. /// </summary> /// <param name="isPrimary">the function indicating if the backend object is primary</param> /// <param name="rm">Ring master object</param> /// <param name="marshaller">the marshaller to use when serializing/deserializing commands</param> internal ScheduledCommand(Func <bool> isPrimary, AbstractRingMaster rm, IByteArrayMarshaller marshaller) { if (isPrimary == null) { throw new ArgumentNullException("isPrimary"); } if (marshaller == null) { throw new ArgumentNullException("marshaller"); } this.marshaller = marshaller; this.isPrimary = isPrimary; this.self = rm; }
/// <summary> /// initializes the pseudonodes tree structure /// </summary> /// <param name="rm">the rm object to use</param> private void InitializePseudoNodesStructure(AbstractRingMaster rm) { // ensure the tree structure is built if (!this.pseudosInitialized) { rm.Create("/$bulkwatcher", null, null, CreateMode.Persistent); rm.Create("/$metadata", null, null, CreateMode.Persistent); foreach (string path in ScheduledCommand.GetPaths()) { rm.Create(path, null, null, CreateMode.PersistentAllowPathCreation); } rm.Delete("/$metadata/ring", -1); rm.Create("/$metadata/clusterreplicaset", null, null, CreateMode.Persistent); rm.Create("/$metadata/health", null, null, CreateMode.Persistent); rm.Create("/$metadata/servicehealing", null, null, CreateMode.Persistent); rm.Create("/$metadata/primary", null, null, CreateMode.Persistent); rm.Create("/$metadata/synchronization/$syncpoint", null, null, CreateMode.PersistentAllowPathCreation); Trace.TraceInformation("PseudoNodes initialized"); this.pseudosInitialized = true; } }
/// <summary> /// discards the connection to the primary, which will unregister all callbacks and destroy all ephemerals. /// </summary> private void DiscardConnectionToPrimary() { this.registeredPath = null; this.self.Close(); this.self = null; }
/// <summary> /// Initiates the logics for the pseudonodes runner. /// </summary> /// <param name="getClientToPrimary">the function to be used to produce a client to the primary</param> /// <param name="monitor">the optional object to use to synchronize executions</param> public void SetupPseudoNodes(Func <AbstractRingMaster> getClientToPrimary, object monitor = null) { this.self = null; this.serviceHealingMgr.Start(); if (monitor == null) { this.monitor = new object(); } else { this.monitor = monitor; } if (getClientToPrimary == null) { throw new ArgumentNullException("getClientToPrimary"); } this.getClientToPrimary = getClientToPrimary; this.timer = new Timer( _ => { try { lock (this.monitor) { if (this.timer == null || this.backend.Factory == null || !this.backend.Factory.IsActive) { Trace.TraceInformation("SetupPseudoNodes: disabling pseudonodes timer"); this.self.Close(); this.timer = null; this.self = null; this.serviceHealingMgr.Stop(); return; } this.OnTimerTriggered(); } } catch (Exception e) { // log e and continue: Trace.TraceWarning("SetupPseudoNodes: {0}", e); } if (this.timer != null && this.backend.Factory != null && this.backend.Factory.IsActive) { Timer timer = this.timer; if (timer != null) { timer.Change(TimerPeriodMillis, Timeout.Infinite); } } }, null, Timeout.Infinite, Timeout.Infinite); this.timer.Change(0, Timeout.Infinite); }