private static IEnumerable <bool> LoadBubblesInto(BubbleGroup group, List <VisualBubble> listToLoadInto, LoadBubbles instance) { if (!listToLoadInto.Any()) { yield break; } Utils.DebugPrint("Loading into convo " + group.ID); var unifiedGroup = group as UnifiedBubbleGroup; var groups = unifiedGroup != null ? unifiedGroup.Groups : new List <BubbleGroup>() { group }; const int MaxLoadPerGroup = 100; var currentTime = listToLoadInto.Min(x => x.Time); var bubbleGroupStates = new Dictionary <BubbleGroup, LoadBubblesIntoStateHolder>(); foreach (var innerGroup in groups) { bubbleGroupStates[innerGroup] = new LoadBubblesIntoStateHolder(); } EventHandler <Service> serviceStarted = (sender, e) => { foreach (var state in bubbleGroupStates) { if (state.Key.Service == e) { state.Value.Dead = false; } } }; ServiceEvents.Started += serviceStarted; instance.ServiceStarted = serviceStarted; while (true) { var listToLoadIntoCount = listToLoadInto.Count; var bubbleLoads = new Dictionary <BubbleGroup, List <Tuple <VisualBubble, bool> > >(); foreach (var innerGroup in groups) { var innerGroupState = bubbleGroupStates[innerGroup]; if (innerGroupState.Dead) { bubbleLoads[innerGroup] = null; continue; } if (innerGroupState.LocalFinished) { var agentBubbles = LoadBubblesIntoDoAgent(innerGroup, currentTime, MaxLoadPerGroup, innerGroupState); if (agentBubbles != null) { bubbleLoads[innerGroup] = agentBubbles.Select(x => new Tuple <VisualBubble, bool>(x, true)).ToList(); } else { bubbleLoads[innerGroup] = null; } } else { var localBubbles = new List <VisualBubble>(); innerGroupState.LocalCursor = BubbleGroupDatabase.FetchBubblesAt(innerGroup, currentTime, MaxLoadPerGroup, ref localBubbles, innerGroupState.LocalCursor); if (innerGroupState.LocalCursor == 0 || localBubbles.Count == 0) { innerGroupState.LocalFinished = true; } if (localBubbles.Count == MaxLoadPerGroup) { bubbleLoads[innerGroup] = localBubbles.Select(x => new Tuple <VisualBubble, bool>(x, false)).ToList(); } else { var innerGroupComparer = innerGroup.Service as Comparer; if (innerGroupComparer != null) { var agentBubbles = LoadBubblesIntoDoAgent(innerGroup, currentTime, MaxLoadPerGroup, innerGroupState); if (agentBubbles == null) { bubbleLoads[innerGroup] = localBubbles.Select(x => new Tuple <VisualBubble, bool>(x, false)).ToList(); } else { var innerGroupAgent = innerGroup.Service as Agent; var combined = new List <Tuple <VisualBubble, bool> >(); // combine them: take all agent bubbles, and then try to replace the clouds with the locals. // what can't be replaced becomes the inserts. for (int i = 0; i < agentBubbles.Count; i++) { var agentBubble = agentBubbles[i]; var localBubble = localBubbles.FirstOrDefault(x => innerGroupComparer.LoadBubblesComparer(x, agentBubble)); if (localBubble != null) { combined.Add(new Tuple <VisualBubble, bool>(localBubble, false)); } else { combined.Add(new Tuple <VisualBubble, bool>(agentBubble, true)); } } bubbleLoads[innerGroup] = combined; } } else { bubbleLoads[innerGroup] = localBubbles.Select(x => new Tuple <VisualBubble, bool>(x, false)).ToList(); } } } } // insert the bubbles into the disa bubble group with two conditions // a) must not be bubble retreived from disa bubble group // b) must not be a duplicate already in the list to load into var listToLoadIntoBubblesOnTime = listToLoadInto.Where(x => x.Time == currentTime).ToList(); foreach (var bubbleLoad in bubbleLoads) { if (bubbleLoad.Value == null) { continue; } var bubbleGroup = bubbleLoad.Key; var bubblesToInsert = LoadBubblesIntoRemoveDuplicates(bubbleLoad.Value.Where(x => x.Item2) .Select(x => x.Item1).ToList(), listToLoadIntoBubblesOnTime); if (bubblesToInsert.Any()) { BubbleGroupDatabase.InsertBubblesByTime(bubbleGroup, bubblesToInsert.ToArray(), int.MaxValue, true, true); } } // find the greatest minimum time of all the bubble loads // and merge the bubble loads against that var greatestMin = 0L; foreach (var bubbleLoad in bubbleLoads) { if (bubbleLoad.Value == null || !bubbleLoad.Value.Any()) { continue; } var min = bubbleLoad.Value.Min(x => x.Item1.Time); if (min > greatestMin) { greatestMin = min; } } var mergedBubbles = new List <VisualBubble>(); foreach (var bubbleLoad in bubbleLoads) { if (bubbleLoad.Value != null) { var bubblesToMerge = bubbleLoad.Value.Where(x => x.Item1.Time >= greatestMin).Select(x => x.Item1).ToList(); foreach (var bubbleToMerge in bubblesToMerge) { bubbleToMerge.BubbleGroupReference = bubbleLoad.Key; } mergedBubbles.AddRange(bubblesToMerge); } } mergedBubbles.TimSort((x, y) => x.Time.CompareTo(y.Time)); // insert the merged bubbles into the list to load into, making sure to // remove and duplicates encountered. listToLoadInto.InsertRange(0, mergedBubbles); LoadBubblesIntoRemoveDuplicates(listToLoadInto, currentTime); if (mergedBubbles.Any()) { currentTime = mergedBubbles.First().Time; } // if the count wasn't altered, we've hit the end if (listToLoadIntoCount == listToLoadInto.Count) { yield break; } yield return(true); } }
private static List <VisualBubble> LoadBubblesIntoDoAgent(BubbleGroup innerGroup, long currentTime, int maxLoadPerGroup, LoadBubblesIntoStateHolder innerGroupState) { var innerGroupAgent = innerGroup.Service as Agent; if (!SupportsSyncAndIsRunning(innerGroup.Service)) { innerGroupState.Dead = true; } else { var bubbles = LoadBubblesIntoQueryAgent(innerGroupAgent, innerGroup, currentTime, maxLoadPerGroup, innerGroupState); return(bubbles); } return(null); }
public static IEnumerable <bool> LoadBubblesIntoOffline(BubbleGroup group, List <VisualBubble> listToLoadInto) { if (!listToLoadInto.Any()) { yield break; } Utils.DebugPrint("Loading into convo (offline): " + group.ID); var unifiedGroup = group as UnifiedBubbleGroup; var groups = unifiedGroup != null ? unifiedGroup.Groups : new List <BubbleGroup>() { group }; const int MaxLoadPerGroup = 100; var currentTime = listToLoadInto.Min(x => x.Time); var bubbleGroupStates = new Dictionary <BubbleGroup, LoadBubblesIntoStateHolder>(); foreach (var innerGroup in groups) { bubbleGroupStates[innerGroup] = new LoadBubblesIntoStateHolder(); } while (true) { var listToLoadIntoCount = listToLoadInto.Count; var bubbleLoads = new Dictionary <BubbleGroup, List <Tuple <VisualBubble, bool> > >(); foreach (var innerGroup in groups) { var innerGroupState = bubbleGroupStates[innerGroup]; if (innerGroupState.LocalFinished) { bubbleLoads[innerGroup] = null; } else { var localBubbles = new List <VisualBubble>(); innerGroupState.LocalCursor = BubbleGroupDatabase.FetchBubblesAt(innerGroup, currentTime, MaxLoadPerGroup, ref localBubbles, innerGroupState.LocalCursor); if (innerGroupState.LocalCursor == 0 || localBubbles.Count == 0) { innerGroupState.LocalFinished = true; } bubbleLoads[innerGroup] = localBubbles.Select(x => new Tuple <VisualBubble, bool>(x, false)).ToList(); } } // find the greatest minimum time of all the bubble loads // and merge the bubble loads against that var greatestMin = 0L; foreach (var bubbleLoad in bubbleLoads) { if (bubbleLoad.Value == null || !bubbleLoad.Value.Any()) { continue; } var min = bubbleLoad.Value.Min(x => x.Item1.Time); if (min > greatestMin) { greatestMin = min; } } var mergedBubbles = new List <VisualBubble>(); foreach (var bubbleLoad in bubbleLoads) { if (bubbleLoad.Value != null) { var bubblesToMerge = bubbleLoad.Value.Where(x => x.Item1.Time >= greatestMin).Select(x => x.Item1).ToList(); foreach (var bubbleToMerge in bubblesToMerge) { bubbleToMerge.BubbleGroupReference = bubbleLoad.Key; } mergedBubbles.AddRange(bubblesToMerge); } } mergedBubbles.TimSort((x, y) => x.Time.CompareTo(y.Time)); // insert the merged bubbles into the list to load into, making sure to // remove and duplicates encountered. listToLoadInto.InsertRange(0, mergedBubbles); LoadBubblesIntoRemoveDuplicates(listToLoadInto, currentTime); if (mergedBubbles.Any()) { currentTime = mergedBubbles.First().Time; } // if the count wasn't altered, we've hit the end if (listToLoadIntoCount == listToLoadInto.Count) { yield break; } yield return(true); } }
private static List <VisualBubble> LoadBubblesIntoQueryAgent(Agent innerGroupAgent, BubbleGroup innerGroup, long currentTime, int maxLoadPerGroup, LoadBubblesIntoStateHolder innerGroupState) { try { var task = innerGroupAgent.LoadBubbles(innerGroup, currentTime, maxLoadPerGroup); task.Wait(); var loadedBubbles = task.Result; if (loadedBubbles == null || loadedBubbles.Count == 0) { innerGroupState.Dead = true; return(null); } else { BubbleManager.AddUrlMarkupIfNeeded(loadedBubbles); return(loadedBubbles); } } catch (Exception ex) { Utils.DebugPrint("Loading bubbles for service " + innerGroup.Service.Information.ServiceName + " on group " + innerGroup.ID + " failed: " + ex); innerGroupState.Dead = true; } return(null); }