/// <summary>
		/// Adds the file to cache and file saving queue if it does not exists.
		/// </summary>
		/// <param name="key">Key to store/retrieve the file.</param>
		/// <param name="bytes">File data in bytes.</param>
		/// <param name="duration">Specifies how long an item should remain in the cache.</param>
		public virtual async Task AddToSavingQueueIfNotExistsAsync(string key, byte[] bytes, TimeSpan duration)
		{
            var sanitizedKey = key.ToSanitizedKey();

            if (!_fileWritePendingTasks.TryAdd(sanitizedKey, 1))
                return;

            await _currentWriteLock.WaitAsync().ConfigureAwait(false); // Make sure we don't add multiple continuations to the same task
            try
            {
                _currentWrite = _currentWrite.ContinueWith(async t =>
                {
                    await Task.Yield(); // forces it to be scheduled for later

                    try
                    {
                        CacheEntry oldEntry;
                        if (_entries.TryGetValue(sanitizedKey, out oldEntry))
                        {
                            string oldFilepath = Path.Combine(_cachePath, oldEntry.FileName);
                            if (File.Exists(oldFilepath))
                                File.Delete(oldFilepath);
                        }

                        string filename = sanitizedKey + "." + (long)duration.TotalSeconds;
                        string filepath = Path.Combine(_cachePath, filename);

                        await FileStore.WriteBytesAsync(filepath, bytes, CancellationToken.None).ConfigureAwait(false);

                        _entries[sanitizedKey] = new CacheEntry(DateTime.UtcNow, duration, filename);
                    }
                    catch (Exception ex) // Since we don't observe the task (it's not awaited, we should catch all exceptions)
                    {
                        Logger.Error(string.Format("An error occured while caching to disk image '{0}'.", key), ex);
                    }
                    finally
                    {
                        byte finishedTask;
                        _fileWritePendingTasks.TryRemove(sanitizedKey, out finishedTask);
				    }
			    });
            }
            finally
            {
                _currentWriteLock.Release();
            }
		}
示例#2
0
		/// <summary>
		/// Adds the file to cache and file saving queue if not exists.
		/// </summary>
		/// <param name="key">Key.</param>
		/// <param name="bytes">Bytes.</param>
		/// <param name="duration">Duration.</param>
		public void AddToSavingQueueIfNotExists(string key, byte[] bytes, TimeSpan duration)
		{
			var sanitizedKey = SanitizeKey(key);

			if (fileWritePendingTasks.TryAdd(sanitizedKey, 1))
			{
				#pragma warning disable 4014
				Task.Run(async () =>
					{
						try
						{
							await fileWriteLock.WaitAsync().ConfigureAwait(false);

							bool existed = entries.ContainsKey(sanitizedKey);
							string filepath = Path.Combine(basePath, sanitizedKey);

							if (!existed)
							{
								using (var fs = FileStore.GetOutputStream(filepath))
								{
									await fs.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
								}						
							}

							AppendToJournal(existed ? JournalOp.Modified : JournalOp.Created, sanitizedKey, DateTime.UtcNow, duration);
							entries[sanitizedKey] = new CacheEntry(DateTime.UtcNow, duration);	
						}
						catch (Exception ex) // Since we don't observe the task (it's not awaited, we should catch all exceptions)
						{
							Console.WriteLine(string.Format("An error occured while caching to disk image '{0}'.", key));
							Console.WriteLine(ex.ToString());
						}
						finally
						{
							byte finishedTask;
							fileWritePendingTasks.TryRemove(sanitizedKey, out finishedTask);
							fileWriteLock.Release();
						}
				});
				#pragma warning restore 4014
			}
		}
示例#3
0
        void InitializeWithJournal()
        {
			lock (lockJournal)
			{
				if(!File.Exists(journalPath))
				{
					using(var writer = new StreamWriter(journalPath, false, encoding))
					{
						writer.WriteLine(Magic);
						writer.WriteLine(version);
					}
					return;
				}

				string line = null;
				using(var reader = new StreamReader(journalPath, encoding))
				{
					if (!EnsureHeader(reader))
						throw new InvalidOperationException("Invalid header");
					
					while((line = reader.ReadLine()) != null)
					{
						try
						{
							var op = ParseOp(line);
							string key;
							DateTime origin;
							TimeSpan duration;

							switch (op)
							{
								case JournalOp.Created:
									ParseEntry(line, out key, out origin, out duration);
									entries.TryAdd(key, new CacheEntry(origin, duration));
									break;
								case JournalOp.Modified:
									ParseEntry(line, out key, out origin, out duration);
									entries[key] = new CacheEntry(origin, duration);
									break;
								case JournalOp.Deleted:
									ParseEntry(line, out key);
									CacheEntry oldEntry;
									entries.TryRemove(key, out oldEntry);
									break;
							}
						}
						catch
						{
						}
					}
				}
			}
        }
示例#4
0
        public async Task AddOrUpdateAsync(string key, Stream stream, CancellationToken token, TimeSpan duration)
        {
            await isInitialized;

            key = SanitizeKey(key);

            bool existed = entries.ContainsKey(key);

			try
			{
				await fileWriteLock.WaitAsync();
				var file = await cacheFolder.CreateFileAsync(key, CreationCollisionOption.ReplaceExisting);

				using (var fs = await file.OpenStreamForWriteAsync())
				{
					await stream.CopyToAsync(fs, BufferSize, token).ConfigureAwait(false);
				}
			}
			finally
			{
				fileWriteLock.Release();
			}

            await AppendToJournal(existed ? JournalOp.Modified : JournalOp.Created,
                key,
                DateTime.UtcNow,
                duration);
            entries[key] = new CacheEntry(DateTime.UtcNow, duration);
        }
        /// <summary>
        /// Adds the file to cache and file saving queue if not exists.
        /// </summary>
        /// <param name="key">Key.</param>
        /// <param name="bytes">Bytes.</param>
        /// <param name="duration">Duration.</param>
        public async Task AddToSavingQueueIfNotExistsAsync(string key, byte[] bytes, TimeSpan duration)
        {
            await initTask.ConfigureAwait(false);

            var sanitizedKey = SanitizeKey(key);

            if (!fileWritePendingTasks.TryAdd(sanitizedKey, 1))
                return;

            await _currentWriteLock.WaitAsync().ConfigureAwait(false); // Make sure we don't add multiple continuations to the same task

            try
            {
                _currentWrite = _currentWrite.ContinueWith(async t =>
                {
                    await Task.Yield(); // forces it to be scheduled for later

                    await initTask.ConfigureAwait(false);

                    try
                    {
                        await fileWriteLock.WaitAsync().ConfigureAwait(false);

                        string filename = sanitizedKey + "." + duration.TotalSeconds;

                        var file = await cacheFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);

                        using (var fs = await file.OpenStreamForWriteAsync().ConfigureAwait(false))
                        {
                            await fs.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
                        }

                        entries[sanitizedKey] = new CacheEntry(DateTime.UtcNow, duration, filename);
                    }
                    catch (Exception ex) // Since we don't observe the task (it's not awaited, we should catch all exceptions)
                    {
                        //TODO WinRT doesn't have Console
                        System.Diagnostics.Debug.WriteLine(string.Format("An error occured while caching to disk image '{0}'.", key));
                        System.Diagnostics.Debug.WriteLine(ex.ToString());
                    }
                    finally
                    {
                        byte finishedTask;
                        fileWritePendingTasks.TryRemove(sanitizedKey, out finishedTask);
                        fileWriteLock.Release();
                    }
                });
            }
            finally
            {
                _currentWriteLock.Release();
            }
        }
示例#6
0
        /// <summary>
        /// Adds the file to cache and file saving queue if not exists.
        /// </summary>
        /// <param name="key">Key.</param>
        /// <param name="bytes">Bytes.</param>
        /// <param name="duration">Duration.</param>
        public async void AddToSavingQueueIfNotExists(string key, byte[] bytes, TimeSpan duration)
        {
            await initTask.ConfigureAwait(false);

            var sanitizedKey = SanitizeKey(key);

			if (fileWritePendingTasks.TryAdd(sanitizedKey, 1))
			{
#pragma warning disable 4014
				Task.Run(async () =>
				{
					await initTask.ConfigureAwait(false);

	            	try
	                {
						await fileWriteLock.WaitAsync().ConfigureAwait(false);

	                    bool existed = entries.ContainsKey(sanitizedKey);

	                    if (!existed)
	                    {
							var file = await cacheFolder.CreateFileAsync(key, CreationCollisionOption.ReplaceExisting);

							using (var fs = await file.OpenStreamForWriteAsync().ConfigureAwait(false))
	                        {
	                            await fs.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
	                        }
	                    }

						await AppendToJournalAsync(existed ? JournalOp.Modified : JournalOp.Created, sanitizedKey, DateTime.UtcNow, duration).ConfigureAwait(false);
	                    entries[sanitizedKey] = new CacheEntry(DateTime.UtcNow, duration);
	                }
					catch (Exception ex) // Since we don't observe the task (it's not awaited, we should catch all exceptions)
					{
                        //TODO WinRT doesn't have Console
						System.Diagnostics.Debug.WriteLine(string.Format("An error occured while caching to disk image '{0}'.", key));
                        System.Diagnostics.Debug.WriteLine(ex.ToString());
					}
	                finally
	                {
						byte finishedTask;
						fileWritePendingTasks.TryRemove(sanitizedKey, out finishedTask);
	                    fileWriteLock.Release();
	                }
	            });
#pragma warning restore 4014
			}
        }
示例#7
0
        async Task InitializeWithJournal()
        {
            await semaphoreSlim.WaitAsync();

            try
            {
                try
                {
                    journalFile = await cacheFolder.GetFileAsync(JournalFileName);
                }
                catch (Exception)
                {
                    journalFile = null;
                }
                
                if (journalFile == null)
                {
                    journalFile = await cacheFolder.CreateFileAsync(JournalFileName, CreationCollisionOption.ReplaceExisting);

                    
                    //using (var stream = await journalFile.OpenStreamForWriteAsync())
                    //using (var writer = new StreamWriter(stream, encoding))
                    //{
                    //    await writer.WriteLineAsync(Magic);
                    //    await writer.WriteLineAsync(version);
                    //    await writer.FlushAsync();
                    //}

                    return;
                }
                else
                {
                    string line = null;

                    using (var stream = await journalFile.OpenStreamForReadAsync())
                    using (var reader = new StreamReader(stream, encoding))
                    {
                        /*
                        if (!EnsureHeader(reader))
                        {
                            throw new InvalidOperationException("Invalid header");
                        }
                        */
                            
                        while ((line = await reader.ReadLineAsync()) != null)
                        {
                            try
                            {
                                var op = ParseOp(line);
                                string key;
                                DateTime origin;
                                TimeSpan duration;

                                switch (op)
                                {
                                    case JournalOp.Created:
                                        ParseEntry(line, out key, out origin, out duration);
                                        entries.TryAdd(key, new CacheEntry(origin, duration));
                                        break;
                                    case JournalOp.Modified:
                                        ParseEntry(line, out key, out origin, out duration);
                                        entries[key] = new CacheEntry(origin, duration);
                                        break;
                                    case JournalOp.Deleted:
                                        ParseEntry(line, out key);
                                        CacheEntry oldEntry;
                                        entries.TryRemove(key, out oldEntry);
                                        break;
                                }
                            }
                            catch
                            {
                                break;
                            }
                        }
                    }
                }
            }
            finally
            {
                semaphoreSlim.Release();
            }
        }
示例#8
0
        async Task InitializeWithJournal()
        {
			await journalLock.WaitAsync().ConfigureAwait(false);

            try
            {
                try
                {
					journalFile = await cacheFolder.GetFileAsync(JournalFileName);
                }
                catch (Exception)
                {
                    journalFile = null;
                }
                
                if (journalFile == null)
                {
					journalFile = await cacheFolder.CreateFileAsync(JournalFileName, CreationCollisionOption.ReplaceExisting);

                    return;
                }
                else
                {
                    string line = null;

					using (var stream = await journalFile.OpenStreamForReadAsync().ConfigureAwait(false))
                    using (var reader = new StreamReader(stream, encoding))
                    {
						while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null)
                        {
                            try
                            {
                                var op = ParseOp(line);
                                string key;
                                DateTime origin;
                                TimeSpan duration;

                                switch (op)
                                {
                                    case JournalOp.Created:
                                        ParseEntry(line, out key, out origin, out duration);
                                        entries.TryAdd(key, new CacheEntry(origin, duration));
                                        break;
                                    case JournalOp.Modified:
                                        ParseEntry(line, out key, out origin, out duration);
                                        entries[key] = new CacheEntry(origin, duration);
                                        break;
                                    case JournalOp.Deleted:
                                        ParseEntry(line, out key);
                                        CacheEntry oldEntry;
                                        entries.TryRemove(key, out oldEntry);
                                        break;
                                }
                            }
                            catch
                            {
                                break;
                            }
                        }
                    }
                }
            }
            finally
            {
                journalLock.Release();
            }
        }
示例#9
0
        /// <summary>
        /// Adds the file to cache and file saving queue if it does not exists.
        /// </summary>
        /// <param name="key">Key to store/retrieve the file.</param>
        /// <param name="bytes">File data in bytes.</param>
        /// <param name="duration">Specifies how long an item should remain in the cache.</param>
        /// <param name="writeFinished">Write finished.</param>
        public virtual async Task AddToSavingQueueIfNotExistsAsync(string key, byte[] bytes, TimeSpan duration, Action writeFinished = null)
        {
            if (!_fileWritePendingTasks.TryAdd(key, 1))
            {
                Logger?.Error("Can't save to disk as another write with the same key is pending: " + key);
                return;
            }

            await _currentWriteLock.WaitAsync().ConfigureAwait(false); // Make sure we don't add multiple continuations to the same task

            try
            {
                _currentWrite = _currentWrite.ContinueWith(async t =>
                {
                    await Task.Yield(); // forces it to be scheduled for later

                    try
                    {
                        if (!Directory.Exists(_cachePath))
                        {
                            Directory.CreateDirectory(_cachePath);
                        }

                        CacheEntry oldEntry;
                        if (_entries.TryGetValue(key, out oldEntry))
                        {
                            string oldFilepath = Path.Combine(_cachePath, oldEntry.FileName);
                            if (File.Exists(oldFilepath))
                            {
                                File.Delete(oldFilepath);
                            }
                        }

                        string filename = key + "." + (long)duration.TotalSeconds;
                        string filepath = Path.Combine(_cachePath, filename);

                        await FileStore.WriteBytesAsync(filepath, bytes, CancellationToken.None).ConfigureAwait(false);

                        _entries[key] = new CacheEntry(DateTime.UtcNow, duration, filename);
                        writeFinished?.Invoke();

                        if (Configuration.VerboseLogging)
                        {
                            Logger?.Debug(string.Format("File {0} saved to disk cache for key {1}", filepath, key));
                        }
                    }
                    catch (Exception ex) // Since we don't observe the task (it's not awaited, we should catch all exceptions)
                    {
                        Logger?.Error(string.Format("An error occured while writing to disk cache for {0}", key), ex);
                    }
                    finally
                    {
                        byte finishedTask;
                        _fileWritePendingTasks.TryRemove(key, out finishedTask);
                    }
                });
            }
            finally
            {
                _currentWriteLock.Release();
            }
        }
示例#10
0
		public async Task AddOrUpdateAsync (string key, Stream stream, CancellationToken token, TimeSpan duration)
		{
			key = SanitizeKey (key);

			bool existed = entries.ContainsKey (key);
			string filepath = Path.Combine(basePath, key);

			try
			{
				await fileWriteLock.WaitAsync();
				using (var fs = FileStore.GetOutputStream(filepath))
				{
					await stream.CopyToAsync(fs, BufferSize, token).ConfigureAwait(false);
				}
			}
			finally
			{
				fileWriteLock.Release();
			}
				
			AppendToJournal (existed ? JournalOp.Modified : JournalOp.Created,
				key,
				DateTime.UtcNow,
				duration);
			entries[key] = new CacheEntry (DateTime.UtcNow, duration);
		}
示例#11
0
        async Task InitializeWithJournal()
        {
            await journalLock.WaitAsync().ConfigureAwait(false);

            try
            {
                try
                {
                    journalFile = await cacheFolder.GetFileAsync(JournalFileName);
                }
                catch (Exception)
                {
                    journalFile = null;
                }

                if (journalFile == null)
                {
                    journalFile = await cacheFolder.CreateFileAsync(JournalFileName, CreationCollisionOption.ReplaceExisting);

                    return;
                }
                else
                {
                    string line = null;

                    using (var stream = await journalFile.OpenStreamForReadAsync().ConfigureAwait(false))
                        using (var reader = new StreamReader(stream, encoding))
                        {
                            while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null)
                            {
                                try
                                {
                                    var      op = ParseOp(line);
                                    string   key;
                                    DateTime origin;
                                    TimeSpan duration;

                                    switch (op)
                                    {
                                    case JournalOp.Created:
                                        ParseEntry(line, out key, out origin, out duration);
                                        entries.TryAdd(key, new CacheEntry(origin, duration));
                                        break;

                                    case JournalOp.Modified:
                                        ParseEntry(line, out key, out origin, out duration);
                                        entries[key] = new CacheEntry(origin, duration);
                                        break;

                                    case JournalOp.Deleted:
                                        ParseEntry(line, out key);
                                        CacheEntry oldEntry;
                                        entries.TryRemove(key, out oldEntry);
                                        break;
                                    }
                                }
                                catch
                                {
                                    break;
                                }
                            }
                        }
                }
            }
            finally
            {
                journalLock.Release();
            }
        }
示例#12
0
        public async Task AddOrUpdateAsync (string key, byte[] data, TimeSpan duration)
        {
            key = SanitizeKey (key);

            bool existed = entries.ContainsKey (key);
            string filepath = Path.Combine(basePath, key);
            await FileStore.WriteBytesAsync(filepath, data).ConfigureAwait(false);

            AppendToJournal (existed ? JournalOp.Modified : JournalOp.Created,
                key,
                DateTime.UtcNow,
                duration);
            entries[key] = new CacheEntry (DateTime.UtcNow, duration);
        }