public void Update() { var absolute = Time.GetNowUnixTimestamp() + Interval; Earliest = absolute - Tolerance; Latest = absolute + Tolerance; }
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); } } } }
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; } }
public static void UpdateLastUnreadSetTime(Service service, string address) { var bubbleGroup = FindWithAddress(service, address); if (bubbleGroup != null) { BubbleGroupSettingsManager.SetLastUnreadSetTime(bubbleGroup, Time.GetNowUnixTimestamp()); } }
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); }
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); }
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); } } } } } } }
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(); } }
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); } }
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(); } }
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(); } } } })); }
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); } } }
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(); } } }); }
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; } })); }
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); } }
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(); }
private static void WriteHeader(BinaryWriter s) { WriteString(s, Time.GetNowUnixTimestamp().ToString(CultureInfo.InvariantCulture)); }
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; } })); }