/// <summary> /// Serializes this instance to the given <see cref="BinaryWriter"/>. /// </summary> /// <param name="binaryWriter">The <see cref="BinaryWriter"/> to serialize to</param> public void WriteTo(BinaryWriter binaryWriter) { if (binaryWriter == null) { throw new ArgumentNullException(nameof(binaryWriter)); } lock (this) { binaryWriter.Write((ulong)this.Id); binaryWriter.Write((string)this.Name); int aclCount = this.Acl == null ? -1 : this.Acl.Count; binaryWriter.Write((int)aclCount); if (aclCount > 0) { for (int i = 0; i < aclCount; i++) { binaryWriter.Write((string)this.Acl[i].Id.Identifier); binaryWriter.Write((string)this.Acl[i].Id.Scheme); binaryWriter.Write((int)this.Acl[i].Perms); } } binaryWriter.Write((long)this.Stat.Mzxid); binaryWriter.Write((long)this.Stat.Czxid); binaryWriter.Write((long)this.Stat.Pzxid); binaryWriter.Write((int)this.Stat.Aversion); binaryWriter.Write((int)this.Stat.Version); binaryWriter.Write((int)this.Stat.Cversion); binaryWriter.Write((long)this.Stat.Mtime); binaryWriter.Write((long)this.Stat.Ctime); if (this.Data == null) { RmAssert.IsTrue(this.Stat.DataLength == 0); binaryWriter.Write((int)-1); } else { RmAssert.IsTrue(this.Stat.DataLength == this.Data.Length); binaryWriter.Write((int)this.Stat.DataLength); binaryWriter.Write((byte[])this.Data); } // Note this may be called in both primary (most of time) and secondaries. The number should not // contain ephemeral nodes. GetChildrenCount() checks the difference between total children and number // of ephemeral nodes (which is 0 on secondaries), and it is the correct number on both primary and // secondaries. binaryWriter.Write((int)this.GetChildrenCount()); ////Trace.TraceInformation($"PersistedData.Write: Id={this.Id} ParentId={this.ParentId} Name={this.Name} #Children={this.GetChildrenCount()} M={this.Stat.Mzxid} NC={this.Stat.NumChildren}/{this.stat.NumEphemeralChildren}"); binaryWriter.Write((ulong)this.ParentId); } }
/// <summary> /// Removes the child. /// </summary> /// <param name="name">The name.</param> public override void RemoveChild(string name) { if (this.Persisted.Node != this) { this.Persisted.Node.RemoveChild(name); return; } IPersistedData pd; bool found = this.childrenMapping.TryGetValue(name, out pd); RmAssert.IsTrue(found); this.childrenMapping.Remove(name); Strategies.MaybeDownscaleDictionary(ref this.childrenMapping); if (pd != null && !pd.IsEphemeral) { this.Persisted.RemoveChild(pd); } }
/// <summary> /// Removes the child. /// </summary> /// <param name="child">The child.</param> public void RemoveChild(IPersistedData child) { if (child == null) { throw new ArgumentNullException("child"); } if (child.Parent == null) { return; } if (child.Parent != this) { RmAssert.Fail("cannot remove a node that is not a child."); } child.Parent = null; this.childrenCount--; }
/// <summary> /// closes this locklist, and commits changes and unlocks all if context gets down to 0 /// </summary> /// <param name="task">async task to indicate the completion of the replication on output</param> /// <returns>true if it needs to be disposed</returns> public bool Complete(out Task task) { ManualResetEvent ev = null; bool abort = this.IsMarkedForAbort(); task = Task.FromResult(0); try { // if this is an abort and we are not in the topmost context, lock down this object so nothing else can be done other that unwind and abort if (abort) { if (this.onAbort != null) { // CAREFUL! this iteration will execute IN REVERSE ORDER. Because elements were inserted each on the first place!!! foreach (Action elem in this.onAbort) { elem(); } } if (this.changelist != null) { this.changelist.Abort(); } } else { List <Action> actions = this.onCommit; this.onCommit = null; // execute all oncommit actions now if (actions != null) { foreach (Action act in actions) { act(); } } if (this.changelist != null && !this.onlyOnEphemeral) { try { if (this.FinishSynchronous) { ev = ManualResetEventPool.InstancePool.GetOne(); this.changelist.CommitSync(this.TxId, ev, out task); } else { this.changelist.Commit(this.TxId, out task); } } catch (Exception e) { RmAssert.Fail("Commit failed: " + e); } RingMasterServerInstrumentation.Instance.OnTxCommitted(); } } } finally { // make sure we unlock the tree in all cases this.changelist = null; this.onAbort = null; this.onCommit = null; this.lockCollections.Release(); } if (ev != null) { ManualResetEventPool.InstancePool.WaitOneAndReturn(ref ev); } return(true); }