internal void AddThreadlines(SyncPacket packet) { foreach (var flow in XRay.FlowMap) { if (!NewStackItems.ContainsKey(flow.ThreadID) || NewStackItems[flow.ThreadID] == 0) { continue; } PairList threadline; if (!Threadlines.TryGetValue(flow.ThreadID, out threadline)) { threadline = new PairList(); Threadlines[flow.ThreadID] = threadline; } int newItems = NewStackItems[flow.ThreadID]; int minDepth = int.MaxValue; int sendCount = Math.Min(newItems, MaxStackItemsPerThreadSent); foreach (var item in flow.EnumerateThreadline(sendCount)) { if (item.Depth < minDepth) { minDepth = item.Depth; } threadline.Add(new Tuple <int, int>((item.Call == null) ? item.NodeID : item.Call.ID, item.Depth)); } // set new items to 0, iterate new items on threadline add NewStackItems[flow.ThreadID] = 0; // send top level of stack, so remote node is in sync (these are often pushed off the threadline) PairList threadstack; if (!ThreadStacks.TryGetValue(flow.ThreadID, out threadstack)) { threadstack = new PairList(); ThreadStacks[flow.ThreadID] = threadstack; } for (int i = minDepth - 1; i >= 0; i--) { var item = flow.Stack[i]; threadstack.Add(new Tuple <int, int>((item.Call == null) ? item.NodeID : item.Call.ID, item.Depth)); } } if (Threadlines.Count > 0) { packet.Threadlines = Threadlines; Threadlines = new Dictionary <int, PairList>(); DataToSend = true; } if (ThreadStacks.Count > 0) { packet.ThreadStacks = ThreadStacks; ThreadStacks = new Dictionary <int, PairList>(); DataToSend = true; } }
public void SendSyncPacket(SyncPacket packet) { int bytesSent = SendPacket(packet); if (bytesSent > 0) { SyncCount++; LastSyncSize = bytesSent; } }
private void Receive_Sync(XConnection connection, G2ReceivedPacket packet) { // received by client from server var sync = SyncPacket.Decode(packet.Root); //Log("Sync packet received"); connection.SyncCount++; connection.LastSyncSize = packet.Root.PacketSize; XRay.RemoteSync(sync); }
private static void ReadPairListMap(ref Dictionary <int, PairList> map, SyncPacket sync, G2Header child) { if (map == null) { map = new Dictionary <int, PairList>(); } int id = 0; PairList list = new PairList(); foreach (var sub in G2Protocol.EnumerateChildren(child)) { if (sub.Name == ChildPacket_ThreadID) { id = BitConverter.ToInt32(sub.Data, sub.PayloadPos); } else if (sub.Name == ChildPacket_PairList) { list = PairList.FromBytes(sub.Data, sub.PayloadPos, sub.PayloadSize); } } map[id] = list; }
private static void ReadPairListMap(ref Dictionary<int, PairList> map, SyncPacket sync, G2Header child) { if (map == null) map = new Dictionary<int, PairList>(); int id = 0; PairList list = new PairList(); foreach (var sub in G2Protocol.EnumerateChildren(child)) if (sub.Name == ChildPacket_ThreadID) id = BitConverter.ToInt32(sub.Data, sub.PayloadPos); else if (sub.Name == ChildPacket_PairList) list = PairList.FromBytes(sub.Data, sub.PayloadPos, sub.PayloadSize); map[id] = list; }
public static SyncPacket Decode(G2Header root) { var sync = new SyncPacket(); foreach (var child in G2Protocol.EnumerateChildren(root)) { switch (child.Name) { case Packet_FunctionHit: sync.FunctionHits = PacketExts.HashSetFromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_ExceptionHit: sync.ExceptionHits = PacketExts.HashSetFromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_ConstructedHit: sync.ConstructedHits = PacketExts.HashSetFromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_DisposedHit: sync.DisposeHits = PacketExts.HashSetFromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_NewCalls: sync.NewCalls = PairList.FromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_CallHits: sync.CallHits = PacketExts.HashSetFromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_CallStats: sync.CallStats = PacketExts.StatsFromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_Inits: sync.Inits = PairList.FromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_NewThreads: if (sync.NewThreads == null) sync.NewThreads = new Dictionary<int, Tuple<string, bool>>(); int id = 0; string name = null; bool alive = false; foreach (var sub in G2Protocol.EnumerateChildren(child)) if (sub.Name == ChildPacket_ThreadID) id = BitConverter.ToInt32(sub.Data, sub.PayloadPos); else if (sub.Name == ChildPacket_ThreadName) name = UTF8Encoding.UTF8.GetString(sub.Data, sub.PayloadPos, sub.PayloadSize); else if (sub.Name == ChildPacket_ThreadAlive) alive = BitConverter.ToBoolean(sub.Data, sub.PayloadPos); sync.NewThreads[id] = new Tuple<string, bool>(name, alive); break; case Packet_ThreadChanges: if (sync.ThreadChanges == null) sync.ThreadChanges = new Dictionary<int, bool>(); int id2 = 0; bool alive2 = false; foreach (var sub in G2Protocol.EnumerateChildren(child)) if (sub.Name == ChildPacket_ThreadID) id2 = BitConverter.ToInt32(sub.Data, sub.PayloadPos); else if (sub.Name == ChildPacket_ThreadAlive) alive2 = BitConverter.ToBoolean(sub.Data, sub.PayloadPos); sync.ThreadChanges[id2] = alive2; break; case Packet_NodeThreads: sync.NodeThreads = PairList.FromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_CallThreads: sync.CallThreads = PairList.FromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_Threadlines: ReadPairListMap(ref sync.Threadlines, sync, child); break; case Packet_ThreadStacks: ReadPairListMap(ref sync.ThreadStacks, sync, child); break; } } return sync; }
public static SyncPacket Decode(G2Header root) { var sync = new SyncPacket(); foreach (var child in G2Protocol.EnumerateChildren(root)) { switch (child.Name) { case Packet_FunctionHit: sync.FunctionHits = PacketExts.HashSetFromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_ExceptionHit: sync.ExceptionHits = PacketExts.HashSetFromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_ConstructedHit: sync.ConstructedHits = PacketExts.HashSetFromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_DisposedHit: sync.DisposeHits = PacketExts.HashSetFromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_NewCalls: sync.NewCalls = PairList.FromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_CallHits: sync.CallHits = PacketExts.HashSetFromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_CallStats: sync.CallStats = PacketExts.StatsFromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_Inits: sync.Inits = PairList.FromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_NewThreads: if (sync.NewThreads == null) { sync.NewThreads = new Dictionary <int, Tuple <string, bool> >(); } int id = 0; string name = null; bool alive = false; foreach (var sub in G2Protocol.EnumerateChildren(child)) { if (sub.Name == ChildPacket_ThreadID) { id = BitConverter.ToInt32(sub.Data, sub.PayloadPos); } else if (sub.Name == ChildPacket_ThreadName) { name = UTF8Encoding.UTF8.GetString(sub.Data, sub.PayloadPos, sub.PayloadSize); } else if (sub.Name == ChildPacket_ThreadAlive) { alive = BitConverter.ToBoolean(sub.Data, sub.PayloadPos); } } sync.NewThreads[id] = new Tuple <string, bool>(name, alive); break; case Packet_ThreadChanges: if (sync.ThreadChanges == null) { sync.ThreadChanges = new Dictionary <int, bool>(); } int id2 = 0; bool alive2 = false; foreach (var sub in G2Protocol.EnumerateChildren(child)) { if (sub.Name == ChildPacket_ThreadID) { id2 = BitConverter.ToInt32(sub.Data, sub.PayloadPos); } else if (sub.Name == ChildPacket_ThreadAlive) { alive2 = BitConverter.ToBoolean(sub.Data, sub.PayloadPos); } } sync.ThreadChanges[id2] = alive2; break; case Packet_NodeThreads: sync.NodeThreads = PairList.FromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_CallThreads: sync.CallThreads = PairList.FromBytes(child.Data, child.PayloadPos, child.PayloadSize); break; case Packet_Threadlines: ReadPairListMap(ref sync.Threadlines, sync, child); break; case Packet_ThreadStacks: ReadPairListMap(ref sync.ThreadStacks, sync, child); break; } } return(sync); }
internal static void RemoteSync(SyncPacket packet) { if (packet.FunctionHits != null) foreach (var id in packet.FunctionHits) { var node = Nodes[id]; node.FunctionHit = ShowTicks; // mark covered if (!CoveredNodes[id]) SetCovered(node); } if (packet.ExceptionHits != null) foreach (var id in packet.ExceptionHits) Nodes[id].ExceptionHit = ShowTicks; if (packet.ConstructedHits != null) foreach (var id in packet.ConstructedHits) Nodes[id].ConstructedHit = ShowTicks; if (packet.DisposeHits != null) foreach (var id in packet.DisposeHits) Nodes[id].DisposeHit = ShowTicks; if (packet.NewCalls != null) foreach (var newCall in packet.NewCalls) { int source = newCall.Item1; int dest = newCall.Item2; int hash = source * FunctionCount + dest; if (!CallMap.Contains(hash)) CreateNewCall(hash, source, Nodes[dest]); else { // on re-connect this will happen //Debug.Assert(false, "New call already added in sync"); } } if (packet.CallHits != null) foreach (var hash in packet.CallHits) { FunctionCall call; if (!CallMap.TryGetValue(hash, out call)) { Debug.Assert(false, "Call not found in sync"); continue; } call.Hit = ShowTicks; if (ClassTracking) TrackClassCall(call, 0); } if (packet.CallStats != null) { foreach (var stat in packet.CallStats) { FunctionCall call; if (!CallMap.TryGetValue(stat.ID, out call)) { Debug.Assert(false, "Call not found in sync"); continue; } call.TotalHits = stat.TotalHits; call.TotalCallTime = stat.TotalCallTime; call.TotalTimeOutsideDest = stat.TotalTimeOutsideDest; } } if (packet.Inits != null) foreach (var init in packet.Inits) { var source = Nodes[init.Item1]; var initClass = Nodes[init.Item2]; CheckCreateInit(source, initClass); } if(packet.NewThreads != null) foreach (var thread in packet.NewThreads) { int id = thread.Key; string name = thread.Value.Item1; bool alive = thread.Value.Item2; if (!FlowMap.Contains(id)) FlowMap.Add(id, new ThreadFlow() { ThreadID = id, Name = name, IsAlive = alive }); else { // on re-connect this will happen //Debug.Assert(false, "Flow already contains thread on sync"); } } if(packet.ThreadChanges != null) foreach (var thread in packet.ThreadChanges) { ThreadFlow flow; if (FlowMap.TryGetValue(thread.Key, out flow)) flow.IsAlive = thread.Value; else Debug.Assert(false, "Thread not found on sync"); } if(packet.NodeThreads != null) foreach (var nodeThread in packet.NodeThreads) { var node = Nodes[nodeThread.Item1]; if (node.ThreadIDs == null) node.ThreadIDs = new HashSet<int>(); node.ThreadIDs.Add(nodeThread.Item2); } if (packet.CallThreads != null) foreach (var callThread in packet.CallThreads) { FunctionCall call; if (!CallMap.TryGetValue(callThread.Item1, out call)) { Debug.Assert(false, "Call thread not found on sync"); continue; } if (call.ThreadIDs == null) call.ThreadIDs = new HashSet<int>(); call.ThreadIDs.Add(callThread.Item2); // add thread to class class (might not exist for internal calls) if (!ClassCallMap.TryGetValue(call.ClassCallHash, out call)) continue; if (call.ThreadIDs == null) call.ThreadIDs = new HashSet<int>(); call.ThreadIDs.Add(callThread.Item2); } if (packet.ThreadStacks != null) foreach (var threadstack in packet.ThreadStacks) { ThreadFlow flow; if (!FlowMap.TryGetValue(threadstack.Key, out flow)) Debug.Assert(false, "Thread not found on sync"); foreach (var itemPos in threadstack.Value) { var item = GetStackItem(itemPos); flow.Stack[item.Depth] = item; } } if(packet.Threadlines != null) foreach (var threadline in packet.Threadlines) { ThreadFlow flow; if (!FlowMap.TryGetValue(threadline.Key, out flow)) Debug.Assert(false, "Thread not found on sync"); // list sent to us latest first, add oldest first threadline.Value.Reverse(); foreach (var itemPos in threadline.Value) { var item = GetStackItem(itemPos); flow.AddStackItem(item); } } }
public bool DoSync() { if (Connection.State != TcpState.Connected) { return(false); } // this is how we throttle the connection to available bandwidth if (!Connection.SendReady) { return(false); } DataToSend = false; // save current set and create a new one so other threads dont get tripped up var packet = new SyncPacket(); AddSet(ref FunctionHits, ref packet.FunctionHits); AddSet(ref ExceptionHits, ref packet.ExceptionHits); AddSet(ref ConstructedHits, ref packet.ConstructedHits); AddSet(ref DisposeHits, ref packet.DisposeHits); AddPairs(ref NewCalls, ref packet.NewCalls); AddSet(ref CallHits, ref packet.CallHits); if (TrackProfiling) { if (packet.CallHits != null) { foreach (var id in packet.CallHits) { CallStats.Add(id); // copy over to stats for bulk send } } if (SendStatsCounter > SendStatsInterval && CallStats.Count > 0) { packet.CallStats = new List <CallStat>(); foreach (var hash in CallStats) { packet.CallStats.Add(new CallStat(XRay.CallMap[hash])); } CallStats = new HashSet <int>(); SendStatsCounter = 0; DataToSend = true; } } AddPairs(ref Inits, ref packet.Inits); if (NewThreads.Count > 0) { packet.NewThreads = NewThreads; NewThreads = new Dictionary <int, Tuple <string, bool> >(); DataToSend = true; } if (ThreadChanges.Count > 0) { packet.ThreadChanges = ThreadChanges; ThreadChanges = new Dictionary <int, bool>(); DataToSend = true; } AddPairs(ref NodeThreads, ref packet.NodeThreads); AddPairs(ref CallThreads, ref packet.CallThreads); if (TrackThreadlines) { AddThreadlines(packet); } // check that there's space in the send buffer to send state if (DataToSend) { Connection.SendSyncPacket(packet); return(true); } return(false); }
public bool DoSync() { if (Connection.State != TcpState.Connected) return false; // this is how we throttle the connection to available bandwidth if (!Connection.SendReady) return false; DataToSend = false; // save current set and create a new one so other threads dont get tripped up var packet = new SyncPacket(); AddSet(ref FunctionHits, ref packet.FunctionHits); AddSet(ref ExceptionHits, ref packet.ExceptionHits); AddSet(ref ConstructedHits, ref packet.ConstructedHits); AddSet(ref DisposeHits, ref packet.DisposeHits); AddPairs(ref NewCalls, ref packet.NewCalls); AddSet(ref CallHits, ref packet.CallHits); if (TrackProfiling) { if (packet.CallHits != null) foreach (var id in packet.CallHits) CallStats.Add(id); // copy over to stats for bulk send if (SendStatsCounter > SendStatsInterval && CallStats.Count > 0) { packet.CallStats = new List<CallStat>(); foreach (var hash in CallStats) packet.CallStats.Add(new CallStat(XRay.CallMap[hash])); CallStats = new HashSet<int>(); SendStatsCounter = 0; DataToSend = true; } } AddPairs(ref Inits, ref packet.Inits); if (NewThreads.Count > 0) { packet.NewThreads = NewThreads; NewThreads = new Dictionary<int, Tuple<string, bool>>(); DataToSend = true; } if (ThreadChanges.Count > 0) { packet.ThreadChanges = ThreadChanges; ThreadChanges = new Dictionary<int, bool>(); DataToSend = true; } AddPairs(ref NodeThreads, ref packet.NodeThreads); AddPairs(ref CallThreads, ref packet.CallThreads); if(TrackThreadlines) AddThreadlines(packet); // check that there's space in the send buffer to send state if (DataToSend) { Connection.SendSyncPacket(packet); return true; } return false; }
internal void AddThreadlines(SyncPacket packet) { foreach (var flow in XRay.FlowMap) { if (!NewStackItems.ContainsKey(flow.ThreadID) || NewStackItems[flow.ThreadID] == 0) continue; PairList threadline; if (!Threadlines.TryGetValue(flow.ThreadID, out threadline)) { threadline = new PairList(); Threadlines[flow.ThreadID] = threadline; } int newItems = NewStackItems[flow.ThreadID]; int minDepth = int.MaxValue; int sendCount = Math.Min(newItems, MaxStackItemsPerThreadSent); foreach (var item in flow.EnumerateThreadline(sendCount)) { if (item.Depth < minDepth) minDepth = item.Depth; threadline.Add(new Tuple<int, int>((item.Call == null) ? item.NodeID : item.Call.ID, item.Depth)); } // set new items to 0, iterate new items on threadline add NewStackItems[flow.ThreadID] = 0; // send top level of stack, so remote node is in sync (these are often pushed off the threadline) PairList threadstack; if (!ThreadStacks.TryGetValue(flow.ThreadID, out threadstack)) { threadstack = new PairList(); ThreadStacks[flow.ThreadID] = threadstack; } for (int i = minDepth - 1; i >= 0; i--) { var item = flow.Stack[i]; threadstack.Add(new Tuple<int, int>((item.Call == null) ? item.NodeID : item.Call.ID, item.Depth)); } } if (Threadlines.Count > 0) { packet.Threadlines = Threadlines; Threadlines = new Dictionary<int, PairList>(); DataToSend = true; } if (ThreadStacks.Count > 0) { packet.ThreadStacks = ThreadStacks; ThreadStacks = new Dictionary<int, PairList>(); DataToSend = true; } }