示例#1
0
        private void StartAndAddTimer(ReminderEntry entry)
        {
            // it might happen that we already have a local reminder with a different eTag
            // if so, stop the local timer for the old reminder, and start again with new info
            // Note: it can happen here that we restart a reminder that has the same eTag as what we just registered ... its a rare case, and restarting it doesn't hurt, so we don't check for it
            var key = new ReminderIdentity(entry.GrainRef, entry.ReminderName);
            LocalReminderData prevReminder;

            if (localReminders.TryGetValue(key, out prevReminder)) // if found locally
            {
                if (Logger.IsVerbose)
                {
                    Logger.Verbose(ErrorCode.RS_LocalStop, "Localy stopping reminder {0} as it is different than newly registered reminder {1}", prevReminder, entry);
                }
                prevReminder.StopReminder(Logger);
                localReminders.Remove(prevReminder.Identity);
            }

            var newReminder = new LocalReminderData(entry);

            localTableSequence++;
            newReminder.LocalSequenceNumber = localTableSequence;
            localReminders.Add(newReminder.Identity, newReminder);
            newReminder.StartTimer(this.RuntimeClient.Scheduler, AsyncTimerCallback, Logger);
            if (Logger.IsVerbose)
            {
                Logger.Verbose(ErrorCode.RS_Started, "Started reminder {0}.", entry.ToString());
            }
        }
示例#2
0
            internal long LocalSequenceNumber; // locally, we use this for resolving races between the periodic table reader, and any concurrent local register/unregister requests

            internal LocalReminderData(ReminderEntry entry)
            {
                Identity            = new ReminderIdentity(entry.GrainRef, entry.ReminderName);
                firstTickTime       = entry.StartAt;
                period              = entry.Period;
                remindable          = entry.GrainRef.Cast <IRemindable>();
                ETag                = entry.ETag;
                LocalSequenceNumber = -1;
            }
示例#3
0
            internal long LocalSequenceNumber; // locally, we use this for resolving races between the periodic table reader, and any concurrent local register/unregister requests

            internal LocalReminderData(ReminderEntry entry, ILoggerFactory loggerFactory)
            {
                Identity            = new ReminderIdentity(entry.GrainRef, entry.ReminderName);
                firstTickTime       = entry.StartAt;
                period              = entry.Period;
                remindable          = entry.GrainRef.Cast <IRemindable>();
                ETag                = entry.ETag;
                LocalSequenceNumber = -1;
                this.timerLogger    = loggerFactory.CreateLogger <GrainTimer>();
            }
示例#4
0
 internal LocalReminderData(ReminderEntry entry, LocalReminderService reminderService)
 {
     Identity             = new ReminderIdentity(entry.GrainRef, entry.ReminderName);
     firstTickTime        = entry.StartAt;
     period               = entry.Period;
     remindable           = entry.GrainRef.Cast <IRemindable>();
     ETag                 = entry.ETag;
     LocalSequenceNumber  = -1;
     this.reminderService = reminderService;
     this.timer           = reminderService.asyncTimerFactory.Create(period, "");
 }
示例#5
0
        // stop without removing it. will remove later.
        private bool TryStopPreviousTimer(GrainReference grainRef, string reminderName)
        {
            // we stop the locally running timer for this reminder
            var key = new ReminderIdentity(grainRef, reminderName);
            LocalReminderData localRem;

            if (!localReminders.TryGetValue(key, out localRem))
            {
                return(false);
            }

            // if we have it locally
            localTableSequence++; // move to next sequence
            localRem.LocalSequenceNumber = localTableSequence;
            localRem.StopReminder(Logger);
            return(true);
        }
示例#6
0
        private async Task ReadTableAndStartTimers(IRingRange range, int rangeSerialNumberCopy)
        {
            if (Logger.IsVerbose)
            {
                Logger.Verbose("Reading rows from {0}", range.ToString());
            }
            localTableSequence++;
            long cachedSequence = localTableSequence;

            try
            {
                var srange = (SingleRange)range;
                ReminderTableData table = await reminderTable.ReadRows(srange.Begin, srange.End); // get all reminders, even the ones we already have

                if (rangeSerialNumberCopy < RangeSerialNumber)
                {
                    if (Logger.IsVerbose)
                    {
                        Logger.Verbose($"My range changed while reading from the table, ignoring the results. Another read has been started. RangeSerialNumber {RangeSerialNumber}, RangeSerialNumberCopy {rangeSerialNumberCopy}.");
                    }
                    return;
                }
                if (StoppedCancellationTokenSource.IsCancellationRequested)
                {
                    return;
                }

                // if null is a valid value, it means that there's nothing to do.
                if (null == table && reminderTable is MockReminderTable)
                {
                    return;
                }

                var remindersNotInTable = localReminders.Where(r => range.InRange(r.Key.GrainRef)).ToDictionary(r => r.Key, r => r.Value); // shallow copy
                if (Logger.IsVerbose)
                {
                    Logger.Verbose("For range {0}, I read in {1} reminders from table. LocalTableSequence {2}, CachedSequence {3}", range.ToString(), table.Reminders.Count, localTableSequence, cachedSequence);
                }

                foreach (ReminderEntry entry in table.Reminders)
                {
                    var key = new ReminderIdentity(entry.GrainRef, entry.ReminderName);
                    LocalReminderData localRem;
                    if (localReminders.TryGetValue(key, out localRem))
                    {
                        if (cachedSequence > localRem.LocalSequenceNumber) // info read from table is same or newer than local info
                        {
                            if (localRem.Timer != null)                    // if ticking
                            {
                                if (Logger.IsVerbose2)
                                {
                                    Logger.Verbose2("In table, In local, Old, & Ticking {0}", localRem);
                                }
                                // it might happen that our local reminder is different than the one in the table, i.e., eTag is different
                                // if so, stop the local timer for the old reminder, and start again with new info
                                if (!localRem.ETag.Equals(entry.ETag))
                                // this reminder needs a restart
                                {
                                    if (Logger.IsVerbose2)
                                    {
                                        Logger.Verbose2("{0} Needs a restart", localRem);
                                    }
                                    localRem.StopReminder(Logger);
                                    localReminders.Remove(localRem.Identity);
                                    StartAndAddTimer(entry);
                                }
                            }
                            else // if not ticking
                            {
                                // no-op
                                if (Logger.IsVerbose2)
                                {
                                    Logger.Verbose2("In table, In local, Old, & Not Ticking {0}", localRem);
                                }
                            }
                        }
                        else // cachedSequence < localRem.LocalSequenceNumber ... // info read from table is older than local info
                        {
                            if (localRem.Timer != null) // if ticking
                            {
                                // no-op
                                if (Logger.IsVerbose2)
                                {
                                    Logger.Verbose2("In table, In local, Newer, & Ticking {0}", localRem);
                                }
                            }
                            else // if not ticking
                            {
                                // no-op
                                if (Logger.IsVerbose2)
                                {
                                    Logger.Verbose2("In table, In local, Newer, & Not Ticking {0}", localRem);
                                }
                            }
                        }
                    }
                    else // exists in table, but not locally
                    {
                        if (Logger.IsVerbose2)
                        {
                            Logger.Verbose2("In table, Not in local, {0}", entry);
                        }
                        // create and start the reminder
                        StartAndAddTimer(entry);
                    }
                    // keep a track of extra reminders ... this 'reminder' is useful, so remove it from extra list
                    remindersNotInTable.Remove(key);
                } // foreach reminder read from table

                int remindersCountBeforeRemove = localReminders.Count;

                // foreach reminder that is not in global table, but exists locally
                foreach (var reminder in remindersNotInTable.Values)
                {
                    if (cachedSequence < reminder.LocalSequenceNumber)
                    {
                        // no-op
                        if (Logger.IsVerbose2)
                        {
                            Logger.Verbose2("Not in table, In local, Newer, {0}", reminder);
                        }
                    }
                    else // cachedSequence > reminder.LocalSequenceNumber
                    {
                        if (Logger.IsVerbose2)
                        {
                            Logger.Verbose2("Not in table, In local, Old, so removing. {0}", reminder);
                        }
                        // remove locally
                        reminder.StopReminder(Logger);
                        localReminders.Remove(reminder.Identity);
                    }
                }
                if (Logger.IsVerbose)
                {
                    Logger.Verbose($"Removed {localReminders.Count - remindersCountBeforeRemove} reminders from local table");
                }
            }
            catch (Exception exc)
            {
                Logger.Error(ErrorCode.RS_FailedToReadTableAndStartTimer, "Failed to read rows from table.", exc);
                throw;
            }
        }