/// <summary> /// Gets the full path to the next file to be received or null if no files /// </summary> /// <param name="cancellationToken"></param> /// <returns></returns> public string Dequeue(CancellationToken cancellationToken) { string fullPath = null; if (!this._TryDequeue(out fullPath)) { // allow only one thread at a time to fill the cache (it is done without locking) if (Interlocked.CompareExchange(ref _accessCounter, 1, 0) > 0) { return(null); } try { // try again, maybe another thread already added items to the queue if (!this._TryDequeue(out fullPath)) { TimeSpan lastNoMessage = TimeSpan.FromTicks(DateTime.Now.Ticks - this._lastNoMessage); if (lastNoMessage.TotalMilliseconds > BACKOFF_NOMSG_MSEC) { var dirName = _queueRegister.EnsureQueueInitialized(this._inputQueue); List <string> tempStore = new List <string>(); // Don't check for defered too often TimeSpan lastNoDefered = TimeSpan.FromTicks(DateTime.Now.Ticks - this._lastNoDefered); if (lastNoDefered.TotalMilliseconds > BACKOFF_DEFERED_MSEC) { int deferedCnt = this._TryFillCacheDefered(tempStore, dirName, cancellationToken); if (deferedCnt == 0) { this._lastNoDefered = DateTime.Now.Ticks; } } int fileCnt = this._TryFillCache(tempStore, dirName, cancellationToken); if (fileCnt == 0) { this._lastNoMessage = DateTime.Now.Ticks; } foreach (string name in tempStore.OrderBy(name => TransportHelper.GetFileUtcDate(name))) { this._filesQueue.Enqueue(name); } this._TryDequeue(out fullPath); } } } finally { Interlocked.CompareExchange(ref _accessCounter, 0, 1); } } return(fullPath); }
private int _TryFillCacheDefered(List <string> tempStore, string dirName, CancellationToken cancellationToken) { DirectoryInfo info = new DirectoryInfo(dirName); var nowUtc = DateTime.Now.ToUniversalTime(); var files = info.EnumerateFiles("d*.json").Where(p => TransportHelper.GetFileUtcDate(p.Name) <= nowUtc).OrderBy(p => p.Name).Take(DEFER_CACHE_SIZE).ToList(); int cnt = 0; foreach (var file in files) { lock (this._filesCacheLock) { if (!this._filesCache.Contains(file.Name)) { tempStore.Add(file.Name); this._filesCache.Add(file.Name); ++cnt; } } cancellationToken.ThrowIfCancellationRequested(); } return(cnt); }