private void CheckExpire(TaskTimer timer) {

            // get the next scheduled item
            NotificationUpdateRecord data;
            lock(_pending) {
                if(_queue.Count == 0) {
                    _queueTimer.Change(_delay, TaskEnv.Current);
                    return;
                }
                Tuplet<DateTime, string> key = _queue.Peek();
                if(key.Item1 > DateTime.UtcNow) {
                    _queueTimer.Change(key.Item1, TaskEnv.Current);
                    return;
                }
                data = _pending[key.Item2];
                _queue.Dequeue();
                _pending.Remove(key.Item2);
            }

            // stuff data into dispatch queue so our worker thread can pick it up and process all data synchronously
            if(!_dispatchQueue.TryEnqueue(data)) {
                throw new InvalidOperationException(string.Format("Enqueue for user '{0}' failed.", data.UserId));
            }

            // check for optimal sleep interval
            lock(_pending) {
                if(_queue.Count == 0) {
                    _queueTimer.Change(_delay, TaskEnv.Current);
                    return;
                }
                Tuplet<DateTime, string> key = _queue.Peek();
                _queueTimer.Change(key.Item1, TaskEnv.Current);
            }
        }
 //--- Constructors ---
 public NotificationDelayQueue(TimeSpan delay, CoroutineHandler<NotificationUpdateRecord, Result> callback) {
     _delay = delay;
     _callback = callback;
     _queueTimer = new TaskTimer(CheckExpire, null);
     _queueTimer.Change(_delay, TaskEnv.None);
     _dispatchQueue = new ProcessingQueue<NotificationUpdateRecord>(Dispatch, 10);
 }
 //--- Constructors ---
 public UpdateDelayQueue(TimeSpan delay, IUpdateRecordDispatcher dispatcher, ITransactionalQueue<XDoc> queue) {
     _delay = delay;
     _dispatcher = dispatcher;
     _queueTimer = TaskTimerFactory.Current.New(_delay, CheckExpire, null, TaskEnv.None);
     _persistentQueue = queue;
     _poll = true;
     _pollTimer = TaskTimerFactory.Current.New(TimeSpan.Zero, Poll, null, TaskEnv.None);
     _log.DebugFormat("created queue with {0} items recovered", queue.Count);
 }
        private void Poll(TaskTimer timer) {
            if(!_poll) {
                timer.Change(TimeSpan.FromSeconds(1), TaskEnv.Current);
                return;
            }
            _poll = false;
            while(true) {

                // pull item from queue to store in out accumulation queue and hold on to it
                var item = _persistentQueue.Dequeue(TimeSpan.MaxValue);
                if(item == null) {

                    // didn't find an item, drop out of loop and set timer to check again later
                    timer.Change(TimeSpan.FromSeconds(1), TaskEnv.Current);
                    return;
                }
                var doc = item.Value;
                var wikiid = doc["@wikiid"].AsText;
                var id = new XUri("http://" + wikiid + "/" + doc["path"].AsText);
                lock(_data) {
                    UpdateRecord data;
                    XUri channel = doc["channel"].AsUri;
                    string action = channel.Segments[2];
                    if(!_data.TryGetValue(id, out data)) {
                        _log.DebugFormat("queueing '{0}' for '{1}'", action, id);
                        _queue.Enqueue(new Tuplet<DateTime, XUri>(DateTime.UtcNow.Add(_delay), id));
                        data = new UpdateRecord(id, doc, wikiid);
                    } else {
                        _log.DebugFormat("appending existing queue record '{0}' for '{1}'", action, id);
                        data = data.With(doc);
                    }
                    if(action != "create" && action != "move") {
                        data.ActionStack.PushDelete();
                    }
                    if(action != "delete") {
                        data.ActionStack.PushAdd();
                    }
                    data.QueueIds.Add(item.Id);
                    _data[id] = data;
                }
            }
        }
Beispiel #5
0
 private static int Compare(TaskTimer left, TaskTimer right)
 {
     return left.When.CompareTo(right.When);
 }
        private void CheckExpire(TaskTimer timer) {
            while(true) {

                // get the next scheduled item
                UpdateRecord data = null;
                lock(_data) {
                    if(_queue.Count == 0) {
                        _queueTimer.Change(_delay, TaskEnv.None);
                        return;
                    }
                    Tuplet<DateTime, XUri> key = _queue.Peek();
                    if(key.Item1 > DateTime.UtcNow) {
                        _queueTimer.Change(key.Item1, TaskEnv.None);
                        return;
                    }
                    data = _data[key.Item2];
                    _queue.Dequeue();
                    _data.Remove(key.Item2);
                }
                Interlocked.Increment(ref _pendingCount);
                _dispatcher.Dispatch(data, new Result(TimeSpan.MaxValue)).WhenDone(r => {

                    // cleanup items from the queue
                    var poll = false;
                    foreach(var itemId in data.QueueIds) {
                        if(!_persistentQueue.CommitDequeue(itemId)) {

                            // if we couldn't take an item, it must have gone back to the queue, so we better poll again
                            poll = true;
                        }
                    }
                    if(poll) {
                        _poll = true;
                    }
                    Interlocked.Decrement(ref _pendingCount);
                    if(r.HasException) {
                        _log.Error(string.Format("dispatch of '{0}' encountered an error", data.Id), r.Exception);
                    }
                });
            }
        }
Beispiel #7
0
 void ITaskTimerOwner.RemoveFromQueue(TaskTimer timer)
 {
     lock(_queue) {
         _queue.Remove(timer);
     }
 }
Beispiel #8
0
 /// <summary>
 /// Create a new timer and set its fire time.
 /// </summary>
 /// <param name="when">Relateive time from now until when the timer should fire.</param>
 /// <param name="handler">The action to invoke when the timer fires.</param>
 /// <param name="state">A state object to associate with the timer.</param>
 /// <param name="env">The environment in which the timer should fire.</param>
 /// <returns>New timer instance.</returns>
 public TaskTimer New(TimeSpan when, Action<TaskTimer> handler, object state, TaskEnv env)
 {
     var result = new TaskTimer(this, handler, state);
     result.Change(when, env);
     return result;
 }
Beispiel #9
0
 void ITaskTimerOwner.AddToQueue(TaskTimer timer, TaskEnv env, TaskTimerStatus next)
 {
     env.Acquire();
     if(timer.Env != null) {
         timer.Env.Release();
     }
     if(_running) {
         lock(_queue) {
             timer.Env = env;
             timer.SetStatus(next);
             _queue.Enqueue(timer);
         }
     } else {
         env.Release();
         timer.Env = null;
         timer.SetStatus(TaskTimerStatus.Done);
     }
 }
Beispiel #10
0
 void ITaskTimerOwner.RemoveFromPending(TaskTimer timer)
 {
     lock(_pending) {
         _pending.Remove(timer);
     }
 }
Beispiel #11
0
 protected void OnInstanceExpireTimer(TaskTimer timer) {
     var wikiId = (string)timer.State;
     _log.DebugFormat("instance '{0}' expired", wikiId);
     OutOfContextShutdown(wikiId);
 }
Beispiel #12
0
 private void Commit(TaskTimer tt) {
     if(_hasUncommittedData) {
         _disposalLock.ExecuteWithReadLock(() => {
             EnsureInstanceNotDisposed();
             lock(_updateSyncroot) {
                 _writer.Commit();
                 _searcherIsStale = true;
                 _hasUncommittedData = false;
             }
         });
     }
     tt.Change(_commitInterval, TaskEnv.None);
 }
 //--- Constructors ---
 public UpdateDelayQueue(TimeSpan delay, IUpdateRecordDispatcher dispatcher) {
     _delay = delay;
     _dispatcher = dispatcher;
     _queueTimer = new TaskTimer(CheckExpire, null);
     _queueTimer.Change(_delay, TaskEnv.None);
 }
Beispiel #14
0
 //--- Constructors ---
 public Listener(string queuename, Action<AwsSqsMessage> callback, IAwsSqsClient client, TaskTimerFactory timerFactory, TimeSpan interval)
 {
     _queuename = queuename;
     _callback = callback;
     _client = client;
     _cache = new ExpiringHashSet<string>(timerFactory);
     _cacheTimer = ((interval.TotalSeconds * 2 < 60) ? 60 : interval.TotalSeconds * 2 + 1).Seconds();
     _pollTimer = timerFactory.New(tt => Coroutine.Invoke(PollSqs, new Result()).WhenDone(r => _pollTimer.Change(interval, TaskEnv.None)), null);
     _pollTimer.Change(0.Seconds(), TaskEnv.None);
 }
Beispiel #15
0
 private void RemoveCachedEntry(TaskTimer timer) {
     lock (_cache) {
         _cache.Remove((string) timer.State);
     }
 }
 private void OnTimer(TaskTimer timer) {
     RemoveCachedEntry((string)timer.State, true);
 }
Beispiel #17
0
        //--- Constructors ---
        public SearchInstanceData(string indexPath, Analyzer analyzer, UpdateDelayQueue queue, TimeSpan commitInterval, TaskTimerFactory taskTimerFactory) {
            _analyzer = analyzer;
            _directory = FSDirectory.GetDirectory(indexPath);

            // Note (arnec): Needed with SimpleFSLock, since a hard shutdown will have left the lock dangling
            IndexWriter.Unlock(_directory);
            try {
                _writer = new IndexWriter(_directory, _analyzer, IndexWriter.MaxFieldLength.UNLIMITED);
            } catch(CorruptIndexException e) {
                _log.WarnFormat("The Search index at {0} is corrupt. You must repair or delete it before restarting the service. If you delete it, you must rebuild your index after service restart.", indexPath);
                if(e.Message.StartsWith("Unknown format version")) {
                    _log.Warn("The index is considered corrupt because it's an unknown version. Did you accidentally downgrade your install?");
                }
                throw;
            }
            _reader = IndexReader.Open(_directory);
            _searcher = new IndexSearcher(_reader);
            _queue = queue;
            _commitInterval = commitInterval;
            _taskTimerFactory = taskTimerFactory;
            if(_commitInterval != TimeSpan.Zero) {
                _commitTimer = _taskTimerFactory.New(_commitInterval, Commit, null, TaskEnv.None);
            }
        }
Beispiel #18
0
 private UserInfo() {
     _expire = new TaskTimer(delegate { IsValidated = false; }, null);
     _isDirty = true;
 }
        protected DekiInstance CreateWikiInstance(string wikiId, XDoc instanceConfig) {
            List<KeyValuePair<string, DekiInstance>> instanceList = null;
            DekiInstance instance = null;
            int instanceCount = 0;

            //throw exception if licensing does not allow startup of another wiki instance
            MindTouch.Deki.Logic.LicenseBL.IsDekiInstanceStartupAllowed(true);

            lock(_instances) {
                instance = GetWikiInstance(wikiId);
                if(instance == null) {

                    _instances[wikiId] = instance = new DekiInstance(_dekiService, wikiId, instanceConfig);
                    instance.InstanceCreationTime = DateTime.UtcNow;
                }

                //Schedule new instance for shutdown if inactive-instance-timeout enabled.
                if(InactiveInstanceTimeOut != TimeSpan.MaxValue) {
                    TaskTimer timer = new TaskTimer(OnInstanceExpireTimer, wikiId);
                    _instanceExpireTimers[wikiId] = timer;
                }

                instanceCount = _instances.Count;
                if(maxInstances != 0 && instanceCount > maxInstances) {
                    instanceList = new List<KeyValuePair<string, DekiInstance>>(_instances);
                }
            }

            //Hit the instance number limit? Look for least recently accessed wiki and shut it down.
            if(instanceList != null) {
                instanceList.Sort(delegate(KeyValuePair<string, DekiInstance> left, KeyValuePair<string, DekiInstance> right) {
                    return DateTime.Compare(left.Value.InstanceLastAccessedTime, right.Value.InstanceLastAccessedTime);
                });

                List<KeyValuePair<string, DekiInstance>> instancesToExamine =
                    instanceList.GetRange(0, instanceList.Count - (int)maxInstances);

                if(instancesToExamine.Count > 0) {
                    Async.Fork(delegate() {
                        foreach(KeyValuePair<string, DekiInstance> instancePair in instancesToExamine) {
                            if((DateTime.UtcNow - instancePair.Value.InstanceLastAccessedTime).TotalSeconds >= MIN_SECS_FROM_ACCESS_TO_SHUTDOWN) {
                                ShutdownInstance(instancePair.Key);
                            }
                        }
                    }, null);
                }
            }

            return instance;
        }
        private void CheckExpire(TaskTimer timer) {
            // get the next scheduled item
            UpdateRecord data = null;
            lock(_data) {
                if(_queue.Count == 0) {
                    _queueTimer.Change(_delay, TaskEnv.Current);
                    return;
                }
                Tuplet<string, DateTime> key = _queue.Peek();
                if(key.Item2 > DateTime.UtcNow) {
                    _queueTimer.Change(key.Item2, TaskEnv.Current);
                    return;
                }
                data = _data[key.Item1];
                _queue.Dequeue();
                _data.Remove(key.Item1);
            }
            _dispatcher.Dispatch(data);

            // check for optimal sleep interval
            lock(_data) {
                if(_queue.Count == 0) {
                    _queueTimer.Change(_delay, TaskEnv.Current);
                    return;
                }
                Tuplet<string, DateTime> key = _queue.Peek();
                _queueTimer.Change(key.Item2, TaskEnv.Current);
            }
        }
 protected void OnInstanceExpireTimer(TaskTimer timer) {
     _log.InfoMethodCall("instance expired", timer.State);
     ShutdownInstance((string)timer.State);
 }
Beispiel #22
0
 private void OnTimer(TaskTimer timer) {
     if(_disposed) {
         return;
     }
     RemoveCachedEntry((string)timer.State);
 }
Beispiel #23
0
 private void OnTimeout(TaskTimer timer) {
     XUri uri = (XUri)timer.State;
     lock(_feeds) {
         _feeds.Remove(uri);
     }
 }
 private CacheEntry() {
     _memoryExpire = new TaskTimer(delegate(TaskTimer tt) {
         _log.DebugFormat("flushing memory cache for '{0}'", Id);
         Cache = null;
     }, null);
 }
Beispiel #25
0
 void ITaskTimerOwner.AddToPending(TaskTimer timer, TaskEnv env, TaskTimerStatus next)
 {
     env.Acquire();
     if(timer.Env != null) {
         timer.Env.Release();
     }
     if(_running) {
         lock(_pending) {
             timer.Env = env;
             timer.SetStatus(next);
             _pending[timer] = null;
         }
     } else {
         env.Release();
         timer.Env = null;
         timer.SetStatus(TaskTimerStatus.Done);
     }
 }