Пример #1
0
            public void Update()
            {
                var absolute = Time.GetNowUnixTimestamp() + Interval;

                Earliest = absolute - Tolerance;
                Latest   = absolute + Tolerance;
            }
Пример #2
0
 private static void SanityCheckup()
 {
     lock (_dbLock)
     {
         using (var db = new SqlDatabase <Entry>(Location))
         {
             const int secondsInWeek     = 604800;
             var       nowTime           = Time.GetNowUnixTimestamp();
             var       truncateTime      = nowTime - secondsInWeek;
             var       removing          = false;
             var       bubblesToTruncate = new List <Entry>();
             foreach (var possibleBubble in db.Store.Where(x => x.Time < truncateTime))
             {
                 if (!removing)
                 {
                     Utils.DebugPrint("Pruning queued bubbles database. Some bubbles are too old!");
                 }
                 removing = true;
                 bubblesToTruncate.Add(possibleBubble);
             }
             foreach (var possibleBubble in bubblesToTruncate)
             {
                 db.Remove(possibleBubble);
             }
         }
     }
 }
Пример #3
0
        public static void SendPresence(Service service, bool available, bool justAddIfNoLastPresence = false)
        {
            if (!service.Information.DoesSupport(typeof(PresenceBubble)))
            {
                return;
            }

            var presenceBubble = new PresenceBubble(Time.GetNowUnixTimestamp(),
                                                    Bubble.BubbleDirection.Outgoing, null,
                                                    false, service, available);

            Utils.DebugPrint("Sending " + (presenceBubble.Available
                ? "available"
                : "unavailble") + " to " +
                             presenceBubble.Service.Information.ServiceName);
            lock (LastPresenceBubbles)
            {
                Action a = () =>
                {
                    LastPresenceBubbles.RemoveAll(pb => pb.Service == presenceBubble.Service);
                    LastPresenceBubbles.Add(presenceBubble);
                };
                if (!justAddIfNoLastPresence)
                {
                    a();
                }
                else
                {
                    var hasPresence = LastPresenceBubbles.Any(x => x.Service == presenceBubble.Service);
                    if (hasPresence)
                    {
                        // do-nothing
                    }
                    else
                    {
                        a();
                    }
                }
            }

            if (!justAddIfNoLastPresence && ServiceManager.IsRunning(service))
            {
                Send(presenceBubble);
            }

            if (justAddIfNoLastPresence)
            {
                return;
            }

            if (available)
            {
                return;
            }
            foreach (var group in BubbleGroupManager.FindAll(service))
            {
                @group.PresenceType = PresenceBubble.PresenceType.Unavailable;
            }
        }
Пример #4
0
        public static void UpdateLastUnreadSetTime(Service service, string address)
        {
            var bubbleGroup = FindWithAddress(service, address);

            if (bubbleGroup != null)
            {
                BubbleGroupSettingsManager.SetLastUnreadSetTime(bubbleGroup, Time.GetNowUnixTimestamp());
            }
        }
Пример #5
0
        internal static UnifiedBubbleGroup CreateUnifiedInternal(List <BubbleGroup> groups, BubbleGroup primaryGroup, string id = null)
        {
            var service = ServiceManager.GetUnified();

            if (service == null)
            {
                return(null);
            }

            var newBubble = new NewBubble(Time.GetNowUnixTimestamp(), Bubble.BubbleDirection.Incoming,
                                          Guid.NewGuid() + "@unified", null, false, service);
            var unified = new UnifiedBubbleGroup(groups, primaryGroup, newBubble, id);

            if (id == null)
            {
                var unread = groups.FirstOrDefault(BubbleGroupSettingsManager.GetUnread) != null;
                BubbleGroupSettingsManager.SetUnread(unified, unread);
            }

            foreach (var group in groups)
            {
                @group.RegisterUnified(unified);
            }

            var associatedPartiallyLoadedGroups = groups.Where(x => x.PartiallyLoaded).ToList();

            if (associatedPartiallyLoadedGroups.Any())
            {
                VisualBubble latest = null;
                foreach (var innerGroup in unified.Groups)
                {
                    var current = innerGroup.Bubbles.Last();
                    if (latest == null || current.Time > latest.Time)
                    {
                        latest = current;
                    }
                }
                if (latest != null)
                {
                    unified.Bubbles.Clear();
                    unified.Bubbles.Add(latest);
                }
                return(unified);
            }

            Populate(unified);

            return(unified);
        }
Пример #6
0
        public static void SendSubscribe(BubbleGroup bubbleGroup, bool subscribe)
        {
            if (!bubbleGroup.Service.Information.DoesSupport(typeof(SubscribeBubble)))
            {
                return;
            }

            var address = bubbleGroup.Address;

            var subcribeBubble = new SubscribeBubble(Time.GetNowUnixTimestamp(),
                                                     Bubble.BubbleDirection.Outgoing, address,
                                                     false, bubbleGroup.Service, subscribe);

            Send(subcribeBubble);
        }
Пример #7
0
        private static IEnumerable <bool?> QueuedBubblesIterator(string serviceName, bool hourLimitation = false,
                                                                 bool removeCurrentlySendingBubbles      = false)
        {
            lock (_dbLock)
            {
                var       currentTime   = Time.GetNowUnixTimestamp();
                const int SecondsInHour = 3600;
                using (var db = new SqlDatabase <Entry>(Location))
                {
                    foreach (var possibleBubble in db.Store.Where(x => serviceName == x.ServiceName))
                    {
                        if (hourLimitation && possibleBubble.Time <= currentTime - SecondsInHour)
                        {
                            continue;
                        }

                        foreach (var bubbleGroup in BubbleGroupManager.BubbleGroupsNonUnified)
                        {
                            if (bubbleGroup.PartiallyLoaded)
                            {
                                continue;
                            }

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

                                if (removeCurrentlySendingBubbles && InsertBubble.IsSending(bubble.ID))
                                {
                                    continue;
                                }

                                if (possibleBubble.Guid == bubble.ID)
                                {
                                    yield return(true);
                                }
                            }
                        }
                    }
                }
            }
        }
Пример #8
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();
            }
        }
Пример #9
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);
            }
        }
Пример #10
0
        private void Load()
        {
            var loadTime = Time.GetNowUnixTimestamp();

            if (!File.Exists(_fileLocation))
            {
                return;
            }

            try
            {
                using (var fs = File.OpenRead(_fileLocation))
                {
                    using (var binaryReader = new BinaryReader(fs))
                    {
                        while (binaryReader.PeekChar() != -1)
                        {
                            var strTime            = ReadHeader(binaryReader);
                            var time               = long.Parse(strTime);
                            var serialiazableBytes = ReadBytes(binaryReader);

                            if (_truncate && _truncateDifference < (loadTime - time))
                            {
                                continue;
                            }

                            using (var ms = new MemoryStream(serialiazableBytes))
                            {
                                var serializableObject = Serializer.Deserialize <TSerializable>(ms);
                                _items.Add(new Container(default(TObject), serializableObject));
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                Utils.DebugPrint("Failed to load database " + typeof(TObject).Name +
                                 ". It is corrupt. Deleting.");
                Delete();
            }
        }
Пример #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
        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);
                }
            }
        }
Пример #13
0
        public static void OnPhoneContactsUpdated()
        {
            Task.Factory.StartNew(() =>
            {
                if (_isUpdating)
                {
                    Utils.DebugPrint("Contacts are already updating... Returning...");
                    return;
                }

                Action action = () =>
                {
                    lock (PhoneBookContactsLock)
                    {
                        using (new PhoneContactsUpdatingDisposable())
                        {
                            if (_phoneBookContacts == null)
                            {
                                Utils.DebugPrint("Phone contacts have not yet been used by the framework/services. Therefore, and update doesn't make sense. Skipping.");
                                return;
                            }

                            LastUpdate = Time.GetNowUnixTimestamp();

                            Utils.DebugPrint("Phone contacts have been updated! Querying phone contacts...");

                            var updatedPhoneContacts = Platform.GetPhoneBookContacts();

                            Utils.DebugPrint("Checking if any numbers/names have been updated...");

                            var updatedPhoneContactsNumbers =
                                (from phoneBookRelation in updatedPhoneContacts
                                 from phoneNumber in phoneBookRelation.PhoneNumbers
                                 select phoneNumber.Number).ToList();

                            var phoneBookContactsNumbers =
                                (from phoneBookRelation in _phoneBookContacts
                                 from phoneNumber in phoneBookRelation.PhoneNumbers
                                 select phoneNumber.Number).ToList();

                            var updatedPhoneContactsFullName =
                                (from phoneBookRelation in updatedPhoneContacts
                                 select phoneBookRelation.FullName).ToList();

                            var phoneContactsFullName =
                                (from phoneBookRelation in _phoneBookContacts
                                 select phoneBookRelation.FullName).ToList();

                            var phoneBooksEqual =
                                updatedPhoneContactsNumbers.Intersect(phoneBookContactsNumbers).Count() ==
                                updatedPhoneContactsNumbers.Union(phoneBookContactsNumbers).Count() &&
                                updatedPhoneContactsFullName.Intersect(phoneContactsFullName).Count() ==
                                updatedPhoneContactsFullName.Union(phoneContactsFullName).Count();

                            if (phoneBooksEqual)
                            {
                                Utils.DebugPrint(
                                    "Phone books are equal. No need to update contacts!");
                                return;
                            }

                            _phoneBookContacts = updatedPhoneContacts;

                            Utils.DebugPrint("Got phone contacts... updating running services...");

                            foreach (
                                var service in
                                ServiceManager.Running)
                            {
                                try
                                {
                                    service.RefreshPhoneBookContacts();
                                    BubbleGroupUpdater.Update(service);
                                }
                                catch (Exception ex)
                                {
                                    Utils.DebugPrint("Service " + service.Information.ServiceName +
                                                     " failed to refresh it contacts. " + ex.Message);
                                }
                            }
                        }
                    }
                };

                if (Time.GetNowUnixTimestamp() - LastUpdate < 10)
                {
                    Utils.DebugPrint(
                        "Contacts were updated less than 10 seconds ago... Waiting 10 seconds...");
                    Platform.ScheduleAction(10000, new WakeLockBalancer.ActionObject(() =>
                    {
                        action();
                    }, WakeLockBalancer.ActionObject.ExecuteType.TaskWithWakeLock));
                }
                else
                {
                    using (Platform.AquireWakeLock("DisaContactsUpdate"))
                    {
                        action();
                    }
                }
            });
        }
Пример #14
0
        private static Task <bool> Send(Bubble b, BubbleGroup group, bool resend)
        {
            return(Task <bool> .Factory.StartNew(() =>
            {
                var vb = b as VisualBubble;
                if (vb != null)
                {
                    if (vb.Status == Bubble.BubbleStatus.Sent)
                    {
                        Utils.DebugPrint("Trying to send a bubble that is already sent! On " + vb.Service.Information.ServiceName);
                        return true;
                    }

                    Func <bool> restartServiceIfNeeded = () =>
                    {
                        if (!ServiceManager.IsRegistered(b.Service) ||
                            ServiceManager.IsRunning(b.Service) ||
                            ServiceManager.IsAborted(b.Service))
                        {
                            return false;
                        }

                        Utils.DebugPrint(
                            "For f***s sakes. The scheduler isn't doing it's job properly, or " +
                            "you're sending a message to it at a weird time. Starting it up bra (" +
                            b.Service.Information.ServiceName + ").");
                        ServiceManager.AbortAndRestart(b.Service);
                        return true;
                    };

                    var visualBubbleServiceId = vb.Service as IVisualBubbleServiceId;
                    if (vb.IdService == null && vb.IdService2 == null && visualBubbleServiceId != null)
                    {
                        visualBubbleServiceId.AddVisualBubbleIdServices(vb);
                    }

                    try
                    {
                        @group = Group(vb, resend, true);
                    }
                    catch (Exception ex)
                    {
                        Utils.DebugPrint("Problem in Send:GroupBubble from service " +
                                         vb.Service.Information.ServiceName + ": " + ex.Message);
                        return false;
                    }

                    if (@group == null)
                    {
                        Utils.DebugPrint("Could not find a suitable group for bubble " + vb.ID
                                         + " on " + vb.Service.Information.ServiceName);
                        return false;
                    }

                    var shouldQueue = vb.Service.QueuedBubblesParameters == null ||
                                      !vb.Service.QueuedBubblesParameters.BubblesNotToQueue.Contains(vb.GetType());

                    try
                    {
                        if (shouldQueue && !resend &&
                            BubbleQueueManager.HasQueuedBubbles(vb.Service.Information.ServiceName,
                                                                true, false))
                        {
                            BubbleQueueManager.JustQueue(group, vb);
                            restartServiceIfNeeded();
                            return false;
                        }

                        if (shouldQueue)
                        {
                            Monitor.Enter(vb.Service.SendBubbleLock);
                        }

                        using (var queued = new BubbleQueueManager.InsertBubble(group, vb, shouldQueue))
                        {
                            Action checkForQueued = () =>
                            {
                                if (!resend &&
                                    BubbleQueueManager.HasQueuedBubbles(vb.Service.Information.ServiceName, true, true))
                                {
                                    BubbleQueueManager.Send(new [] { vb.Service.Information.ServiceName });
                                }
                            };

                            try
                            {
                                FailBubbleIfPathDoesntExist(vb);
                                SendBubbleInternal(b);
                            }
                            catch (ServiceQueueBubbleException ex)
                            {
                                Utils.DebugPrint("Queuing visual bubble on service " +
                                                 vb.Service.Information.ServiceName + ": " + ex.Message);

                                UpdateStatus(vb, Bubble.BubbleStatus.Waiting, @group);

                                if (!restartServiceIfNeeded())
                                {
                                    checkForQueued();
                                }

                                return false;
                            }
                            catch (Exception ex)
                            {
                                queued.CancelQueue();

                                Utils.DebugPrint("Visual bubble on " +
                                                 vb.Service.Information.ServiceName + " failed to be sent: " +
                                                 ex);

                                UpdateStatus(vb, Bubble.BubbleStatus.Failed, @group);
                                BubbleGroupEvents.RaiseBubbleFailed(vb, @group);

                                if (!restartServiceIfNeeded())
                                {
                                    checkForQueued();
                                }

                                //FIXME: if the bubble fails to send, allow the queue manager to continue.
                                if (resend)
                                {
                                    return true;
                                }

                                return false;
                            }

                            queued.CancelQueue();

                            lock (BubbleGroupManager.LastBubbleSentTimestamps)
                            {
                                BubbleGroupManager.LastBubbleSentTimestamps[group.ID] = Time.GetNowUnixTimestamp();
                            }

                            if (vb.Status == Bubble.BubbleStatus.Delivered)
                            {
                                Utils.DebugPrint(
                                    "************ Race condition. The server set the status to delivered/read before we could send it to sent. :')");
                                checkForQueued();
                                return true;
                            }

                            UpdateStatus(vb, Bubble.BubbleStatus.Sent, @group);

                            checkForQueued();
                            return true;
                        }
                    }
                    finally
                    {
                        if (shouldQueue)
                        {
                            Monitor.Exit(vb.Service.SendBubbleLock);
                        }
                    }
                }
                else
                {
                    var composeBubble = b as ComposeBubble;

                    if (composeBubble != null)
                    {
                        var bubbleToSend = composeBubble.BubbleToSend;
                        var visualBubbleServiceId = bubbleToSend.Service as IVisualBubbleServiceId;
                        if (bubbleToSend.IdService == null && bubbleToSend.IdService2 == null &&
                            visualBubbleServiceId != null)
                        {
                            visualBubbleServiceId.AddVisualBubbleIdServices(bubbleToSend);
                        }
                        @group.InsertByTime(bubbleToSend);
                        try
                        {
                            BubbleGroupEvents.RaiseBubbleInserted(bubbleToSend, @group);
                        }
                        catch
                        {
                            // do nothing
                        }
                    }

                    try
                    {
                        SendBubbleInternal(b);
                    }
                    catch (ServiceBubbleGroupAddressException ex)
                    {
                        if (!String.IsNullOrWhiteSpace(ex.Address))
                        {
                            if (composeBubble != null)
                            {
                                composeBubble.BubbleToSend.Address = ex.Address;
                                composeBubble.BubbleToSend.Status = Bubble.BubbleStatus.Sent;

                                var actualGroup = Group(composeBubble.BubbleToSend, resend, true);

                                ServiceEvents.RaiseComposeFinished(
                                    @group as ComposeBubbleGroup, actualGroup);

                                return true;
                            }
                        }

                        composeBubble.BubbleToSend.Status = Bubble.BubbleStatus.Failed;
                        return false;
                    }
                    catch (Exception ex)
                    {
                        Utils.DebugPrint("Failed to send bubble on service " + b.Service.Information.ServiceName);

                        if (composeBubble != null)
                        {
                            composeBubble.BubbleToSend.Status = Bubble.BubbleStatus.Failed;
                        }

                        return false;
                    }

                    if (composeBubble != null)
                    {
                        composeBubble.BubbleToSend.Status = Bubble.BubbleStatus.Failed;
                        return false;
                    }

                    return true;
                }
            }));
        }
Пример #15
0
        public static long FetchBubblesOnDay(BubbleGroup group, Stream stream, Action <VisualBubble> updateCallback,
                                             int day, long cursor = -1, string[] bubbleTypes = null, Func <VisualBubble, bool> comparer = null)
        {
            var lowerTime = Time.GetNowUnixTimestamp() - (day * 86400);
            var upperTime = lowerTime + 86400 + 600;

            lock (OperationLock)
            {
                stream.Seek(cursor == -1 ? stream.Length : cursor, SeekOrigin.Begin);
                long streamPosition;

                while (true)
                {
                    streamPosition = stream.Position;

                    if (stream.Position == 0)
                    {
                        return(-2);
                    }

                    var    found = false;
                    byte[] headerBytes;
                    int    headerBytesLength;
                    int    endPosition;

                    if (bubbleTypes == null)
                    {
                        BubbleGroupDatabasePrimitives.ReadBubbleHeader(stream, out headerBytes, out headerBytesLength);
                        BubbleGroupDatabasePrimitives.FindBubbleHeaderDelimiter(headerBytes, headerBytesLength, 0, out endPosition);
                        found = true;
                    }
                    else
                    {
                        var bubbleType = BubbleGroupDatabasePrimitives.ReadBubbleHeaderType(stream, out headerBytes,
                                                                                            out headerBytesLength, out endPosition);
                        for (var x = 0; x < bubbleTypes.Length; x++)
                        {
                            if (bubbleTypes[x] != bubbleType)
                            {
                                continue;
                            }
                            found = true;
                            break;
                        }
                    }

                    if (found)
                    {
                        var guid = BubbleGroupDatabasePrimitives.ReadBubbleHeaderStruct(headerBytes, headerBytesLength,
                                                                                        endPosition + 1, out endPosition);
                        var time = BubbleGroupDatabasePrimitives.AsciiBytesToString(headerBytes, endPosition + 1,
                                                                                    headerBytesLength);
                        long longTime;
                        Int64.TryParse(time, out longTime);

                        if (longTime < lowerTime)
                        {
                            break;
                        }

                        if (longTime > upperTime)
                        {
                            BubbleGroupDatabasePrimitives.JumpBubbleData(stream);
                            continue;
                        }

                        var bubbleData = BubbleGroupDatabasePrimitives.ReadBubbleData(stream);

                        var visualBubble = Deserialize(bubbleData);
                        if (visualBubble == null)
                        {
                            continue;
                        }
                        if (comparer != null && !comparer(visualBubble))
                        {
                            continue;
                        }
                        visualBubble.Service = @group.Service;
                        visualBubble.ID      = guid;
                        visualBubble.BubbleGroupReference = @group;
                        updateCallback(visualBubble);
                    }
                    else
                    {
                        BubbleGroupDatabasePrimitives.JumpBubbleData(stream);
                    }
                }

                return(streamPosition);
            }
        }
Пример #16
0
        public static void SetNotQueuedToFailures(BubbleGroup group)
        {
            var nowUnixTimeStamp = Time.GetNowUnixTimestamp();

            var groups = BubbleGroupManager.GetInner(@group).Where(x =>
                                                                   (x.Service.QueuedBubblesParameters != null &&
                                                                    x.Service.QueuedBubblesParameters.BubblesNotToQueue != null &&
                                                                    x.Service.QueuedBubblesParameters.BubblesNotToQueue.Any()));

            if (!groups.Any())
            {
                return;
            }

            foreach (var innerGroup in groups)
            {
                if (HasNotQueued(innerGroup))
                {
                    if (innerGroup.PartiallyLoaded)
                    {
                        BubbleGroupFactory.LoadFullyIfNeeded(innerGroup);
                    }

                    var bubblesSetToFailed = new List <VisualBubble>();

                    foreach (var bubble in innerGroup.Bubbles)
                    {
                        if (bubble.Direction == Bubble.BubbleDirection.Outgoing &&
                            bubble.Status == Bubble.BubbleStatus.Waiting)
                        {
                            if (innerGroup
                                .Service.QueuedBubblesParameters.BubblesNotToQueue
                                .FirstOrDefault(x => x == bubble.GetType()) != null)
                            {
                                var failBubble = innerGroup
                                                 .Service.QueuedBubblesParameters.SendingBubblesToFailOnServiceStart
                                                 .FirstOrDefault(x => x == bubble.GetType()) != null;

                                // Older than 10 minutes, fail it regardless.
                                if (!failBubble && bubble.Time < (nowUnixTimeStamp - 600))
                                {
                                    failBubble = true;
                                }

                                if (failBubble)
                                {
                                    RemoveNotQueued(bubble);
                                    bubble.Status = Bubble.BubbleStatus.Failed;
                                    bubblesSetToFailed.Add(bubble);
                                }
                            }
                        }
                    }

                    if (bubblesSetToFailed.Any())
                    {
                        BubbleGroupDatabase.UpdateBubble(innerGroup, bubblesSetToFailed.ToArray(), 100);
                        foreach (var bubble in bubblesSetToFailed)
                        {
                            BubbleGroupEvents.RaiseBubbleFailed(bubble, innerGroup);
                        }
                        BubbleGroupEvents.RaiseBubblesUpdated(innerGroup);
                        BubbleGroupEvents.RaiseRefreshed(innerGroup);
                    }
                }
            }

            NotQueuedSanityCheckup();
        }
Пример #17
0
 private static void WriteHeader(BinaryWriter s)
 {
     WriteString(s, Time.GetNowUnixTimestamp().ToString(CultureInfo.InvariantCulture));
 }
Пример #18
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 nowUnixTimestamp = Time.GetNowUnixTimestamp();

                    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)
                    {
                        var hasPossibleBubble = possibleBubblesFromDatabase.FirstOrDefault(x =>
                                                                                           x.BubbleGroupGuid != null && x.BubbleGroupGuid == bubbleGroup.ID) != null;
                        if (!hasPossibleBubble)
                        {
                            continue;
                        }

                        if (bubbleGroup.PartiallyLoaded)
                        {
                            BubbleGroupFactory.LoadFullyIfNeeded(bubbleGroup);
                        }

                        var bubblesToSetToFail = new List <Tuple <Entry, VisualBubble> >();
                        foreach (var bubble in bubbleGroup.Bubbles)
                        {
                            if (bubble.Status != Bubble.BubbleStatus.Waiting)
                            {
                                continue;
                            }

                            if (bubble.Direction != Bubble.BubbleDirection.Outgoing)
                            {
                                continue;
                            }

                            var possibleBubbleFromDatabase = possibleBubblesFromDatabase.FirstOrDefault(x => x.Guid == bubble.ID);
                            if (possibleBubbleFromDatabase != null)
                            {
                                // older than 10 minutes, fail
                                if (bubble.Time < (nowUnixTimestamp - 600))
                                {
                                    bubble.Status = Bubble.BubbleStatus.Failed;
                                    bubblesToSetToFail.Add(Tuple.Create(possibleBubbleFromDatabase, bubble));
                                    continue;
                                }

                                possibleBubblesInDisa.Add(new Tuple <Entry, VisualBubble>(possibleBubbleFromDatabase, bubble));
                            }
                        }
                        if (bubblesToSetToFail.Any())
                        {
                            BubbleGroupDatabase.UpdateBubble(bubbleGroup,
                                                             bubblesToSetToFail.Select(x => x.Item2).ToArray(), 100);
                            Remove(bubblesToSetToFail.Select(x => x.Item1).ToArray());
                            foreach (var bubble in bubblesToSetToFail)
                            {
                                BubbleGroupEvents.RaiseBubbleFailed(bubble.Item2, bubbleGroup);
                            }
                            BubbleGroupEvents.RaiseBubblesUpdated(bubbleGroup);
                            BubbleGroupEvents.RaiseRefreshed(bubbleGroup);
                        }
                    }

                    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
                            }
                        }
                    });

                    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);
                            }
                        }
                    }

                    SanityCheckup();

                    return receipts;
                }
            }));
        }