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; } } }
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); } }); } }
void ITaskTimerOwner.RemoveFromQueue(TaskTimer timer) { lock(_queue) { _queue.Remove(timer); } }
/// <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; }
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); } }
void ITaskTimerOwner.RemoveFromPending(TaskTimer timer) { lock(_pending) { _pending.Remove(timer); } }
protected void OnInstanceExpireTimer(TaskTimer timer) { var wikiId = (string)timer.State; _log.DebugFormat("instance '{0}' expired", wikiId); OutOfContextShutdown(wikiId); }
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); }
//--- 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); }
private void RemoveCachedEntry(TaskTimer timer) { lock (_cache) { _cache.Remove((string) timer.State); } }
private void OnTimer(TaskTimer timer) { RemoveCachedEntry((string)timer.State, true); }
//--- 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); } }
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); }
private void OnTimer(TaskTimer timer) { if(_disposed) { return; } RemoveCachedEntry((string)timer.State); }
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); }
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); } }