コード例 #1
0
        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);
        }
コード例 #2
0
        public static bool LoadFullyIfNeeded(BubbleGroup group, bool sync = false)
        {
            if (@group == null)
            {
                return(false);
            }

            var loadedSomething = false;

            lock (BubbleGroupDatabase.OperationLock)
            {
                var unifiedGroup = @group as UnifiedBubbleGroup;

                var associatedGroups = unifiedGroup != null
                    ? unifiedGroup.Groups.ToList()
                    : new[] { @group }.ToList();
                var associatedPartiallyLoadedGroups = associatedGroups.Where(x => x.PartiallyLoaded).ToList();
                foreach (var partiallyLoadedGroup in associatedPartiallyLoadedGroups)
                {
                    loadedSomething = true;
                    var partiallyLoadedBubblesToRemove = partiallyLoadedGroup.Bubbles.ToList();
                    foreach (var bubble in BubbleGroupDatabase.FetchBubbles(partiallyLoadedGroup).Reverse())
                    {
                        partiallyLoadedGroup.Bubbles.Add(bubble);
                    }
                    foreach (var partiallyLoadedBubbleToRemove in partiallyLoadedBubblesToRemove)
                    {
                        partiallyLoadedGroup.Bubbles.Remove(partiallyLoadedBubbleToRemove);
                    }
                    partiallyLoadedGroup.PartiallyLoaded = false;
                }

                if (unifiedGroup != null && !unifiedGroup.UnifiedGroupLoaded)
                {
                    Populate(unifiedGroup);
                }
            }

            if (!sync && loadedSomething)
            {
                Task.Factory.StartNew(() =>
                {
                    var unifiedGroup = @group as UnifiedBubbleGroup;
                    if (unifiedGroup != null)
                    {
                        BubbleQueueManager.Send(unifiedGroup.Groups.Where(x => ServiceManager.IsRunning(x.Service))
                                                .Select(x => x.Service.Information.ServiceName).ToArray());
                    }
                    else if (ServiceManager.IsRunning(@group.Service))
                    {
                        BubbleQueueManager.Send(new[] { @group.Service.Information.ServiceName });
                    }
                    BubbleManager.SetNotQueuedToFailures(@group);
                });
            }

            return(loadedSomething);
        }
コード例 #3
0
 public Result(Type resultType, string newActionId, VisualBubble[] updates, VisualBubble[] inserts)
 {
     NewActionId = newActionId;
     Updates     = updates;
     Inserts     = inserts;
     ResultType  = resultType;
     BubbleManager.AddUrlMarkupIfNeeded(updates);
     BubbleManager.AddUrlMarkupIfNeeded(inserts);
 }
コード例 #4
0
        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);
            }
        }
コード例 #5
0
        private static void SetUnread(BubbleGroup group, bool unread, bool updateUi = true, bool skipSendReadBubble = false, bool onlySetIfServiceRunning = true)
        {
            var unifiedGroup = @group as UnifiedBubbleGroup;

            if (unifiedGroup != null)
            {
                foreach (var innerGroup in unifiedGroup.Groups)
                {
                    SetUnread(innerGroup, false, skipSendReadBubble);
                }
            }

            Action @do = () =>
            {
                var updatedSomething = BubbleGroupSettingsManager.GetUnread(@group);
                BubbleGroupSettingsManager.SetUnread(@group, unread);

                if (unifiedGroup == null)
                {
                    if (!skipSendReadBubble)
                    {
                        if (@group.Service.Information.DoesSupport(typeof(ReadBubble)) && ServiceManager.IsRunning(@group.Service))
                        {
                            BubbleManager.Send(new ReadBubble(Time.GetNowUnixTimestamp(), Bubble.BubbleDirection.Outgoing,
                                                              @group.Service, @group.Address, null, Time.GetNowUnixTimestamp(), @group.IsParty, updatedSomething));
                        }
                    }
                }

                if (updateUi)
                {
                    BubbleGroupEvents.RaiseRefreshed(@group);
                }
            };

            if (onlySetIfServiceRunning && ServiceManager.IsRunning(@group.Service))
            {
                @do();
            }
            else if (!onlySetIfServiceRunning)
            {
                @do();
            }
        }
コード例 #6
0
        private static void SetUnread(BubbleGroup group, bool unread, bool updateUi = true, bool skipSendReadBubble = false, bool onlySetIfServiceRunning = true)
        {
            var unifiedGroup = @group as UnifiedBubbleGroup;

            if (unifiedGroup != null)
            {
                foreach (var innerGroup in unifiedGroup.Groups)
                {
                    SetUnread(innerGroup, unread, false, skipSendReadBubble, onlySetIfServiceRunning);
                }
            }

            var currentlyUnread = BubbleGroupSettingsManager.GetUnread(@group);

            if ((onlySetIfServiceRunning && ServiceManager.IsRunning(@group.Service)) || !onlySetIfServiceRunning)
            {
                BubbleGroupSettingsManager.SetUnread(@group, unread);
                if (unifiedGroup == null)
                {
                    if (!skipSendReadBubble)
                    {
                        if (@group.Service.Information.DoesSupport(typeof(ReadBubble)) && ServiceManager.IsRunning(@group.Service))
                        {
                            var readBubble = new ReadBubble(Time.GetNowUnixTimestamp(), Bubble.BubbleDirection.Outgoing,
                                                            @group.Service, @group.Address, null, Time.GetNowUnixTimestamp(), @group.IsParty, currentlyUnread);
                            if (@group.IsExtendedParty)
                            {
                                readBubble.ExtendedParty = true;
                            }
                            BubbleManager.Send(readBubble);
                        }
                    }
                }
                if (updateUi)
                {
                    BubbleGroupEvents.RaiseRefreshed(@group);
                }
            }
            else
            {
                BubbleGroupSettingsManager.SetUnreadOffline(@group, unread);
            }
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        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);
                        });
                    }
                }
            }));
        }
コード例 #9
0
        internal static void OnBubbleReceived(Bubble b)
        {
            var visualBubble = b as VisualBubble;

            if (visualBubble != null)
            {
                try
                {
                    BubbleManager.Group(visualBubble);
                }
                catch (Exception ex)
                {
                    Utils.DebugPrint("Problem in OnBubbleReceived (VisualBubble) from service " +
                                     visualBubble.Service.Information.ServiceName + ": " + ex.Message);
                }

                if (visualBubble.Direction == Bubble.BubbleDirection.Incoming &&
                    IsRunning(visualBubble.Service) &&
                    BubbleQueueManager.HasQueuedBubbles(b.Service.Information.ServiceName, true, true))
                {
                    Utils.DebugPrint("Sending queued bubbles as we're getting some received.");
                    BubbleQueueManager.Send(new [] { b.Service.Information.ServiceName });
                }
            }
            else if (b is AbstractBubble)
            {
                Utils.DebugPrint("We got an abstract bubble: " + b.GetType().Name + " Address: " + b.Address);

                BubbleGroup group = null;

                var deliveredBubble = b as DeliveredBubble;
                if (deliveredBubble != null)
                {
                    @group = BubbleGroupManager.FindWithAddress(deliveredBubble.Service, deliveredBubble.Address);

                    if (@group != null)
                    {
                        BubbleGroupFactory.LoadFullyIfNeeded(@group);

                        var bubbles = @group.Bubbles;

                        for (var i = bubbles.Count - 1; i >= 0; i--)
                        {
                            var bubble = bubbles[i];

                            if (bubble.ID != deliveredBubble.VisualBubbleID)
                            {
                                continue;
                            }

                            BubbleManager.UpdateStatus(bubble, Bubble.BubbleStatus.Delivered, @group);

                            if (@group.Service.Information.DoesSupport(typeof(DeliveredBubbleReceipt)))
                            {
                                BubbleManager.Send(new DeliveredBubbleReceipt(Time.GetNowUnixTimestamp(), Bubble.BubbleDirection.Outgoing,
                                                                              @group.Service, bubble));
                            }

                            break;
                        }
                    }
                }

                var readBubble = b as ReadBubble;
                if (readBubble != null)
                {
                    @group = BubbleGroupManager.FindWithAddress(readBubble.Service, readBubble.Address);
                    if (@group != null)
                    {
                        BubbleGroupFactory.LoadFullyIfNeeded(@group);

                        if (@group.ReadTimes == null || [email protected])
                        {
                            @group.ReadTimes = new []
                            {
                                new DisaReadTime
                                {
                                    ParticipantAddress = readBubble.ParticipantAddress,
                                    Time = readBubble.ReadTime
                                }
                            };
                        }
                        else
                        {
                            var readTimes = @group.ReadTimes.ToList();

                            var duplicateReadTime = readTimes.FirstOrDefault(x =>
                                                                             @group.Service.BubbleGroupComparer(x.ParticipantAddress, readBubble.ParticipantAddress));
                            if (duplicateReadTime != null)
                            {
                                readTimes.Remove(duplicateReadTime);
                            }

                            readTimes.Add(new DisaReadTime
                            {
                                ParticipantAddress = readBubble.ParticipantAddress,
                                Time = readBubble.ReadTime
                            });

                            @group.ReadTimes = readTimes.ToArray();
                        }
                    }
                }

                var prescenceBubble = b as PresenceBubble;
                if (prescenceBubble != null)
                {
                    @group = BubbleGroupManager.Find(bubbleGroup =>
                                                     !bubbleGroup.IsParty &&
                                                     bubbleGroup.Service ==
                                                     prescenceBubble.Service &&
                                                     prescenceBubble.Service.BubbleGroupComparer(
                                                         bubbleGroup.Address,
                                                         prescenceBubble.Address));

                    if (@group != null)
                    {
                        if ([email protected] && !prescenceBubble.Available)
                        {
                            var oldPresence = @group.PresenceType;
                            @group.PresenceType = PresenceBubble.PresenceType.Unavailable;
                            if (oldPresence != prescenceBubble.Presence)
                            {
                                BubbleGroupManager.UpdateLastOnline(@group);
                            }
                        }
                        else
                        {
                            @group.PresenceType         = prescenceBubble.Presence;
                            @group.PresencePlatformType = prescenceBubble.Platform;
                        }

                        if (!prescenceBubble.Available)
                        {
                            @group.Typing = false;
                        }
                    }
                }

                var typingBubble = b as TypingBubble;
                if (typingBubble != null)
                {
                    @group = BubbleGroupManager.Find(bubbleGroup =>
                                                     !bubbleGroup.IsParty &&
                                                     bubbleGroup.Service ==
                                                     typingBubble.Service &&
                                                     typingBubble.Service.BubbleGroupComparer(
                                                         bubbleGroup.Address,
                                                         typingBubble.Address));

                    if (@group != null)
                    {
                        if (@group.Presence)
                        {
                            @group.Typing        = typingBubble.Typing;
                            @group.TypingIsAudio = typingBubble.IsAudio;
                        }
                        else
                        {
                            @group.Typing = false;
                        }
                    }
                }

                try
                {
                    if (@group != null)
                    {
                        BubbleGroupEvents.RaiseNewAbstractBubble(b as AbstractBubble, @group);
                    }
                }
                catch (Exception ex)
                {
                    Utils.DebugPrint("Problem in OnBubbleReceived (AbstractBubble) from service " +
                                     b.Service.Information.ServiceName + ": " + ex.Message);
                }
            }
        }
コード例 #10
0
        public static Task <List <Receipt> > Send(string[] serviceNames, bool scheduled = false)
        {
            return(Task <List <Receipt> > .Factory.StartNew(() =>
            {
                //PROCESS:  1) find all bubbles under serviceNames in db
                //          2) relate db entries to bubbles loaded into memory by Disa
                //          3) parallel send bubbles based respective to service
                //          4) delete all successful bubbles out of db

                lock (_sendLock)
                {
                    var possibleBubblesFromDatabase = new List <Entry>();

                    lock (_dbLock)
                    {
                        using (var db = new SqlDatabase <Entry>(Location))
                        {
                            foreach (var possibleBubble in db.Store.Where(x => serviceNames.Contains(x.ServiceName)).Reverse())
                            {
                                if (!InsertBubble.IsSending(possibleBubble.Guid))
                                {
                                    possibleBubblesFromDatabase.Add(possibleBubble);
                                }
                            }
                        }
                    }

                    var possibleBubblesInDisa = new List <Tuple <Entry, VisualBubble> >();
                    foreach (var bubbleGroup in BubbleGroupManager.BubbleGroupsNonUnified)
                    {
                        if (bubbleGroup.PartiallyLoaded)
                        {
                            continue;
                        }

                        foreach (var bubble in bubbleGroup)
                        {
                            if (bubble.Status != Bubble.BubbleStatus.Waiting)
                            {
                                continue;
                            }

                            var possibleBubbleFromDatabase = possibleBubblesFromDatabase.FirstOrDefault(x => x.Guid == bubble.ID);
                            if (possibleBubbleFromDatabase != null)
                            {
                                possibleBubblesInDisa.Add(new Tuple <Entry, VisualBubble>(possibleBubbleFromDatabase, bubble));
                            }
                        }
                    }

                    var sent = new List <Tuple <Entry, bool> >();

                    var possibleBubblesInDisaByService = possibleBubblesInDisa.GroupBy(x => x.Item1.ServiceName);
                    Parallel.ForEach(possibleBubblesInDisaByService, possibleBubblesInService =>
                    {
                        var failed = false;
                        foreach (var possibleBubble in possibleBubblesInService)
                        {
                            if (failed)
                            {
                                sent.Add(new Tuple <Entry, bool>(possibleBubble.Item1, false));
                                continue;
                            }

                            Utils.DebugPrint(">>>>>>>>>>> Sending queued bubble on "
                                             + possibleBubble.Item2.Service.Information.ServiceName + "!");

                            var sendBubbleTask = BubbleManager.Send(possibleBubble.Item2, true);
                            sendBubbleTask.Wait();
                            if (sendBubbleTask.Result)
                            {
                                Utils.DebugPrint(">>>>>>>>> Successfully sent queued bubble on " +
                                                 possibleBubble.Item2.Service.Information.ServiceName + "!");
                                sent.Add(new Tuple <Entry, bool>(possibleBubble.Item1, true));
                                lock (_dbLock)
                                {
                                    using (var db = new SqlDatabase <Entry>(Location))
                                    {
                                        db.Remove(possibleBubble.Item1);
                                    }
                                }
                                Utils.Delay(100).Wait();
                            }
                            else
                            {
                                Utils.DebugPrint(">>>>>>>>> Failed to send queued bubble on " +
                                                 possibleBubble.Item2.Service.Information.ServiceName + "!");
                                sent.Add(new Tuple <Entry, bool>(possibleBubble.Item1, false));
                                failed = true; // fail the entire chain for this service from here on out so messages aren't sent out of order
                            }
                        }
                    });

                    SanityCheckup();

                    var receipts = sent.Select(x => new Receipt(x.Item1.Guid, x.Item2)).ToList();

                    if (!scheduled)
                    {
                        if (receipts.FirstOrDefault(x => !x.Success) != null)
                        {
                            ScheduleReSend(serviceNames);
                        }
                        else
                        {
                            var needToSendAgain = serviceNames.Where(x => BubbleQueueManager.HasQueuedBubbles(x, true, true)).ToArray();
                            if (needToSendAgain.Any())
                            {
                                Send(needToSendAgain);
                            }
                        }
                    }

                    return receipts;
                }
            }));
        }
コード例 #11
0
        public static Task Sync(BubbleGroup group, bool force = false)
        {
            return(Task.Factory.StartNew(() =>
            {
                Utils.DebugPrint("Syncing convo " + group.ID);

                lock (SyncLock)
                {
                    Utils.DebugPrint("Syncing convo " + group.ID + " (after lock)");

                    var somethingSynced = false;

                    var groupsToSync = new List <BubbleGroup>();

                    var unifiedGroup = group as UnifiedBubbleGroup;
                    if (unifiedGroup != null)
                    {
                        groupsToSync.AddRange(unifiedGroup.Groups);
                    }
                    else
                    {
                        groupsToSync.Add(group);
                    }

                    foreach (var groupToSync in groupsToSync)
                    {
                        if (!groupToSync.NeedsSync && !force)
                        {
                            continue;
                        }

                        var groupToSyncAgent = groupToSync.Service as Agent;

                        if (groupToSyncAgent == null)
                        {
                            continue;
                        }

                        if (!ServiceManager.IsRunning(groupToSync.Service))
                        {
                            continue;
                        }

                        somethingSynced = true;

                        try
                        {
                            ReSync:
                            var syncTime = Time.GetNowUnixTimestamp();
                            var syncTask = groupToSyncAgent.Sync(groupToSync, Database.GetActionId(groupToSync));
                            syncTask.Wait();
                            var syncResult = syncTask.Result;
                            if (!syncResult.EmptyResult && !syncResult.NullActionId && !syncResult.JustRefresh)
                            {
                                lock (BubbleGroupDatabase.OperationLock)
                                {
                                    if (syncResult.ResultType == Result.Type.Purge)
                                    {
                                        if (BubbleGroupManager.LastBubbleSentTimestamps.ContainsKey(groupToSync.ID))
                                        {
                                            lock (BubbleGroupManager.LastBubbleSentTimestamps)
                                            {
                                                var lastBubbleSentTime = BubbleGroupManager.LastBubbleSentTimestamps[groupToSync.ID];
                                                if (lastBubbleSentTime >= syncTime)
                                                {
                                                    Utils.DebugPrint("Sync has detected that a bubble was sent during the time the sync was fetched. Redoing sync...");
                                                    goto ReSync;
                                                }
                                            }
                                        }
                                        Utils.DebugPrint("Sync is purging the database for bubble group " + groupToSync.ID
                                                         + " on service " + groupToSync.Service.Information.ServiceName);
                                        BubbleGroupDatabase.Kill(groupToSync);
                                    }
                                    if (!syncResult.EmptyInserts)
                                    {
                                        Utils.DebugPrint("Sync is inserting " + syncResult.Inserts.Length
                                                         + " bubbles into " + groupToSync.ID + " on service " + groupToSync.Service.Information.ServiceName);
                                        if (syncResult.ResultType == Result.Type.Purge)
                                        {
                                            syncResult.Inserts.TimSort((x, y) => x.Time.CompareTo(y.Time));
                                            BubbleGroupDatabase.AddBubbles(groupToSync, syncResult.Inserts);
                                            // If a purge is issued, then we need to carry over all sending bubbles to the new BubbleGroup being created.
                                            // Additionally, we need to remove any sending bubbles that are already on the insert list to avoid duplicates.
                                            var sendingBubbles = BubbleManager.FetchAllSending(groupToSync).ToList();
                                            var sendingBubblesFiltered = new List <VisualBubble>();
                                            foreach (var sendingBubble in sendingBubbles)
                                            {
                                                var hasInsertBubble = syncResult.Inserts.FirstOrDefault(x => x.ID == sendingBubble.ID) != null;
                                                if (!hasInsertBubble)
                                                {
                                                    sendingBubblesFiltered.Add(sendingBubble);
                                                }
                                            }
                                            if (sendingBubblesFiltered.Any())
                                            {
                                                BubbleGroupDatabase.InsertBubblesByTime(groupToSync, sendingBubblesFiltered.ToArray(), SearchDepth);
                                            }
                                        }
                                        else
                                        {
                                            BubbleGroupDatabase.InsertBubblesByTime(groupToSync, syncResult.Inserts, SearchDepth);
                                        }
                                    }
                                    if (!syncResult.EmptyUpdates)
                                    {
                                        Utils.DebugPrint("Sync is updating " + syncResult.Updates.Length
                                                         + " bubbles into " + groupToSync.ID + " on service " + groupToSync.Service.Information.ServiceName);
                                        BubbleManager.Update(groupToSync, syncResult.Updates, SearchDepth);
                                    }
                                }
                            }
                            else
                            {
                                Utils.DebugPrint("Sync for bubble group " +
                                                 groupToSync.ID + " on service " + groupToSync.Service.Information.ServiceName +
                                                 " returned an empty result (" + syncResult.ResultType.ToString() + ").");
                            }
                            if (!syncResult.NullActionId)
                            {
                                Database.SetActionId(groupToSync, syncResult.NewActionId);
                            }
                            groupToSync.NeedsSync = false;
                        }
                        catch (Exception ex)
                        {
                            Utils.DebugPrint("Failed to sync bubble group " + groupToSync.ID
                                             + " on service " + groupToSync.Service.Information.ServiceName + ": " + ex);
                        }
                    }

                    if (somethingSynced)
                    {
                        lock (BubbleGroupDatabase.OperationLock)
                        {
                            // Here we need to replace all the sending or downloading bubbles with the 'real' ones.
                            // If this is never done, then on the UI, a 'sending' will never be set to 'sent', and any download
                            // progress will never be updated. Why? Different memory objects.
                            var sendingBubbles = BubbleManager.FetchAllSendingAndDownloading(group).ToList();
                            BubbleGroupFactory.UnloadFullLoad(group);
                            BubbleGroupFactory.LoadFullyIfNeeded(group, true);
                            if (sendingBubbles.Any())
                            {
                                BubbleManager.Replace(group, sendingBubbles);
                            }
                            group.RaiseBubblesSynced();
                        }
                    }
                }
            }));
        }
コード例 #12
0
        public static Task Sync(BubbleGroup group, bool force = false)
        {
            return(Task.Factory.StartNew(() =>
            {
                Utils.DebugPrint("Syncing convo " + group.ID);

                lock (SyncLock)
                {
                    Utils.DebugPrint("Syncing convo " + group.ID + " (after lock)");

                    var somethingSynced = true;

                    var groupsToSync = new List <BubbleGroup>();

                    var unifiedGroup = group as UnifiedBubbleGroup;
                    if (unifiedGroup != null)
                    {
                        groupsToSync.AddRange(unifiedGroup.Groups);
                    }
                    else
                    {
                        groupsToSync.Add(group);
                    }

                    foreach (var groupToSync in groupsToSync)
                    {
                        if (!groupToSync.NeedsSync && !force)
                        {
                            continue;
                        }

                        var groupToSyncAgent = groupToSync.Service as Agent;

                        if (groupToSyncAgent == null)
                        {
                            continue;
                        }

                        if (!ServiceManager.IsRunning(groupToSync.Service))
                        {
                            continue;
                        }

                        try
                        {
                            var syncTask = groupToSyncAgent.Sync(groupToSync, Database.GetActionId(groupToSync));
                            syncTask.Wait();
                            var syncResult = syncTask.Result;
                            if (!syncResult.EmptyResult && !syncResult.NullActionId && !syncResult.JustRefresh)
                            {
                                lock (BubbleGroupDatabase.OperationLock)
                                {
                                    if (syncResult.ResultType == Result.Type.Purge)
                                    {
                                        Utils.DebugPrint("Sync is purging the database for bubble group " + groupToSync.ID
                                                         + " on service " + groupToSync.Service.Information.ServiceName);
                                        BubbleGroupDatabase.Kill(groupToSync);
                                    }
                                    if (!syncResult.EmptyInserts)
                                    {
                                        Utils.DebugPrint("Sync is inserting " + syncResult.Inserts.Length
                                                         + " bubbles into " + groupToSync.ID + " on service " + groupToSync.Service.Information.ServiceName);
                                        if (syncResult.ResultType == Result.Type.Purge)
                                        {
                                            syncResult.Inserts.TimSort((x, y) => x.Time.CompareTo(y.Time));
                                            BubbleGroupDatabase.AddBubbles(groupToSync, syncResult.Inserts);
                                        }
                                        else
                                        {
                                            BubbleGroupDatabase.InsertBubblesByTime(groupToSync, syncResult.Inserts, SearchDepth);
                                        }
                                    }
                                    if (!syncResult.EmptyUpdates)
                                    {
                                        Utils.DebugPrint("Sync is updating " + syncResult.Updates.Length
                                                         + " bubbles into " + groupToSync.ID + " on service " + groupToSync.Service.Information.ServiceName);
                                        BubbleManager.Update(groupToSync, syncResult.Updates, SearchDepth);
                                    }
                                    Database.SetActionId(groupToSync, syncResult.NewActionId);
                                }
                            }
                            else
                            {
                                Utils.DebugPrint("Sync for bubble group " +
                                                 groupToSync.ID + " on service " + groupToSync.Service.Information.ServiceName +
                                                 " returned an empty result (" + syncResult.ResultType.ToString() + ").");
                                somethingSynced = syncResult.JustRefresh;
                            }
                            groupToSync.NeedsSync = false;
                        }
                        catch (Exception ex)
                        {
                            Utils.DebugPrint("Failed to sync bubble group " + groupToSync.ID
                                             + " on service " + groupToSync.Service.Information.ServiceName + ": " + ex);
                            somethingSynced = false;
                        }
                    }

                    if (somethingSynced)
                    {
                        lock (BubbleGroupDatabase.OperationLock)
                        {
                            var sendingBubbles = BubbleManager.FetchAllSendingAndDownloading(group).ToList();
                            BubbleGroupFactory.UnloadFullLoad(group);
                            BubbleGroupFactory.LoadFullyIfNeeded(group, true);
                            if (sendingBubbles.Any())
                            {
                                BubbleManager.Replace(group, sendingBubbles);
                            }
                            group.RaiseBubblesSynced();
                        }
                    }
                }
            }));
        }