internal static void UpdateLastOnline(BubbleGroup bubbleGroup, bool updateUi = true, bool fromProcessUpdateLastOnlineQueue = false) { var service = bubbleGroup.Service; if (!fromProcessUpdateLastOnlineQueue) { if (!ServiceManager.IsRunning(service) && !bubbleGroup.IsParty) { lock (UpdateLastOnlineQueue) UpdateLastOnlineQueue.Add(new Tuple <BubbleGroup, bool>(bubbleGroup, updateUi)); return; } } if (!ServiceManager.IsRunning(service) || bubbleGroup.IsParty) { return; } // reject the last online update if the Presence is currently available if (bubbleGroup.Presence) { return; } try { service.GetBubbleGroupLastOnline(bubbleGroup, time => { // reject the last online update if the Presence is currently available if (bubbleGroup.Presence) { return; } bubbleGroup.PresenceType = PresenceBubble.PresenceType.Unavailable; bubbleGroup.LastSeen = time; if (updateUi) { BubbleGroupEvents.RaiseInformationUpdated(bubbleGroup); } //we constantly need to subscribe to a bubble group. doing it //in last online method is the most effective. BubbleManager.SendSubscribe(bubbleGroup, true); //Presence(service, true); }); } catch (Exception ex) { Utils.DebugPrint("Error updating bubble group last online: " + service.Information.ServiceName + ": " + ex.Message); } }
private static BubbleGroup AddNewInternal(VisualBubble newBubble, bool raiseBubbleInserted) { var group = new BubbleGroup(newBubble, null, false); BubbleGroupSettingsManager.SetUnreadIndicatorGuid(group, group.LastBubbleSafe().ID, true); if (ServiceManager.IsRunning(@group.Service)) { newBubble.Service.NewBubbleGroupCreated(@group).ContinueWith(x => { // force the UI to refetch the photo @group.IsPhotoSetFromService = false; BubbleManager.SendSubscribe(@group, true); BubbleGroupUpdater.Update(@group); }); } BubbleGroupManager.BubbleGroupsAdd(@group); BubbleGroupDatabase.AddBubble(@group, newBubble); if (raiseBubbleInserted) { try { BubbleGroupEvents.RaiseBubbleInserted(newBubble, @group); } catch (Exception ex) { Utils.DebugPrint( "Error in notifying the interface that the bubble group has been updated (" + newBubble.Service.Information.ServiceName + "): " + ex.Message); } } BubbleGroupUpdater.Update(@group); return(@group); }
public static Task Start(Service service, bool smartStart = false, int smartStartSeconds = 10) { return(Task.Factory.StartNew(() => { using (var wakeLock = Platform.AquireWakeLock("DisaStart")) { if (IsRunning(service)) { Utils.DebugPrint( "The service is already running. Preventing possible deadlock. SmartStart? " + smartStart); return; } if (IsStarting(service)) { Utils.DebugPrint( "The service is being started. Preventing possible deadlock. SmartStart? " + smartStart); return; } Action epilogue = () => { GetFlags(service).Starting = false; }; lock (service) { GetFlags(service).Aborted = false; GetFlags(service).AbortedSpecial = false; GetFlags(service).Starting = true; GetFlags(service).ManualSettingsNeeded = false; Utils.DebugPrint("Loading settings for service " + service.Information.ServiceName); try { var settings = SettingsManager.Load(service); if (settings == null) { Utils.DebugPrint("Failed to load saved settings for " + service.Information.ServiceName + ". Will try to initialize with no settings..."); if (!service.InitializeDefault()) { Utils.DebugPrint( "Service doesn't allow initializing without settings. Needs manual input."); GetFlags(service).ManualSettingsNeeded = true; ServiceEvents.RaiseServiceManualSettingsNeeded(service); } else { Utils.DebugPrint("Service initialized under no settings."); } } else { Utils.DebugPrint("Loading saved settings! Initializing..."); if (service.Initialize(settings)) { Utils.DebugPrint("Successfully initialized service!"); } else { Utils.DebugPrint("Failed to initialize service. Needs manual input."); GetFlags(service).ManualSettingsNeeded = true; ServiceEvents.RaiseServiceManualSettingsNeeded(service); } } } catch (Exception ex) { Utils.DebugPrint("Failed: " + ex); epilogue(); return; } Utils.DebugPrint("Starting service " + service.Information.ServiceName); try { if (service.Information.UsesInternet && !Platform.HasInternetConnection()) { throw new Exception("No internet connection. Cannot connect service: " + service.Information.ServiceName); } StartInternal(service, wakeLock); } catch (ServiceSchedulerException ex) { Utils.DebugPrint("Problem in scheduler: " + ex.Message); epilogue(); return; } catch (ServiceSpecialRestartException) { Utils.DebugPrint("Service " + service.Information.ServiceName + " is asking to be restarted on connect/authenticate. This should be called sparingly, Disa can easily " + "break under these circumstances. Restarting..."); StopInternal(service); epilogue(); Start(service, smartStart, smartStartSeconds); return; } catch (ServiceExpiredException) { Utils.DebugPrint("The service " + service.Information.ServiceName + " has expired. :("); GetFlags(service).Aborted = true; GetFlags(service).Expired = true; ServiceEvents.RaiseServiceExpired(service); StopInternal(service); epilogue(); return; } catch (Exception ex) { if (smartStart) { StopInternal(service, false); if (smartStartSeconds > 600) { Utils.DebugPrint("Service " + service.Information.ServiceName + " needs to wait over 10minutes to be restarted." + " Killing SmartStart. The service will not be restarted. Reason: " + ex); epilogue(); return; } Utils.DebugPrint("Service " + service.Information.ServiceName + " failed to be started. SmartStart enabled. " + "Service being scheduled to be re-started in T-" + smartStartSeconds + " seconds! Reason: " + ex); var hasSmartStart = new object(); service.HasSmartStart = hasSmartStart; Platform.ScheduleAction(smartStartSeconds, new WakeLockBalancer.ActionObject(() => { if (IsAborted(service)) { Utils.DebugPrint( "Service " + service.Information .ServiceName + " tried to be started, but it deemed killed."); return; } if (service.HasSmartStart != hasSmartStart) { Utils.DebugPrint( "This smart start has been invalidated. There " + "seems to be another one on the block."); return; } Utils.DebugPrint( "Smart start is firing the service " + service.Information .ServiceName + " up again!"); StopInternal(service); Start(service, true, smartStartSeconds * 2); }, WakeLockBalancer.ActionObject.ExecuteType.TaskWithWakeLock)); epilogue(); return; } Utils.DebugPrint("Failed to start service " + service.Information.ServiceName + " (No SmartStart) : " + ex); StopInternal(service, false); epilogue(); return; } BubbleManager.SendSubscribe(service, true); BubbleManager.SendLastPresence(service); service.ReceivingBubblesThread = new Thread(() => { try { StartReceiveBubbles(service); } catch (ThreadAbortException) { Utils.DebugPrint( "Abort thread excepton in receiving bubbles on service (outer thread) " + service.Information.ServiceName); } catch (Exception ex) { Utils.DebugPrint(">>>>>>>>> " + ex.Message + " " + ex.StackTrace); } Utils.DebugPrint("Receiving bubbles for service " + service.Information.ServiceName + " has come to an end."); }); service.ReceivingBubblesThread.Start(); GetFlags(service).Starting = false; BubbleManager.SetNotQueuedToFailures(service); Utils.Delay(1000).ContinueWith(x => { BubbleGroupSync.ResetSyncsIfHasAgent(service); BubbleGroupUpdater.Update(service); BubbleQueueManager.Send(new[] { service.Information.ServiceName }); BubbleGroupManager.ProcessUpdateLastOnlineQueue(service); }); } } })); }