public static CacheItemInfo FromFileName(string fileName) { if (!fileName.StartsWith(CacheDirectoryPrefix)) { fileName = Path.GetFileName(fileName); string[] parts = fileName .Split(FileNameSeparator); if (parts.Length == 4) { string uniqueKey = DecodePathName(parts[0]); var item = new CacheItemInfo(uniqueKey) { ExpirationTime = new DateTime(Int64.Parse(parts[2])), UpdatedTime = new DateTime(Int64.Parse(parts[3])), IsOptimized = Boolean.Parse(parts[1]) }; return(item); } } return(null); }
public override void Write(CacheItemInfo info, byte[] data) { var fi = new FileItem(info); PriorityQueue.AddStorageWorkItem(() => { lock (LockObject) { for (int r = 0; r < WriteRetries; r++) { try { FileItem.EnsurePath(IsoStore, fi.FileName); using (Stream stream = IsoStore.OpenFile(fi.FileName, FileMode.Create, FileAccess.Write, FileShare.None)) { stream.Write(data, 0, data.Length); stream.Flush(); } _cache[info.UniqueName] = info; break; } catch (IsolatedStorageException) { Debug.WriteLine("Exception writing file: Name={0}, Length={1}", fi.FileName, data.Length); // These IsolatedStorageExceptions seem to happen at random, // haven't yet found a repro. So for the retry, // if we failed, sleep for a bit and then try again. // Thread.Sleep(50); } } } }); }
private static string ToFileName(CacheItemInfo item) { string name = EncodePathName(item.UniqueName); name = String.Format("{1}{0}{2}{0}{3}{0}{4}", FileNameSeparator, name, item.IsOptimized, item.ExpirationTime.Ticks, item.UpdatedTime.Ticks); name = Path.Combine(DirectoryHash(item.UniqueName), name); return(name); }
public static void Main() { var cii = new CacheItemInfo(); var data = new CustomClass { { 1, 1 }, { 2, 2 }, { 3, 3 } }; GetCacheCollectionValues(ref cii, data); Console.WriteLine(cii.Count); // expect 3 }
/// <summary> /// Adds or replaces an item in the cache /// </summary> /// <param name="cacheItemInfo"></param> public void Put(CacheItemInfo cacheItemInfo) { ArgumentValidation.NotNull(cacheItemInfo, "entry"); var itemKey = CreateKey(cacheItemInfo.Key.Profile.ProfileName, cacheItemInfo.Key.Key); var timeout = cacheItemInfo.Key.Profile.GetTimeout(); var expiry = timeout.HasValue ? DateTime.Now + timeout.Value : Cache.NoAbsoluteExpiration; GetMemoryCache(cacheItemInfo.Key.Profile).Set( itemKey, cacheItemInfo.Item, expiry); }
public void TestLoadFromCache() { // populate the cache with an item. // string uniqueName = CacheEntry.BuildUniqueName(typeof(ShortCacheObject), new LoadContext("LFC")); var cii = new CacheItemInfo(uniqueName, DateTime.Now, DateTime.Now.AddHours(1)); DataManager.StoreProvider.Write(cii, ShortCacheObject.SCOLoadRequest.WriteToStream("LoadFromCache", -1).GetBuffer()); Thread.Sleep(250); // let the write happen; // sync load that value. // var value = DataManager.Current.LoadFromCache <ShortCacheObject>("LFC"); Assert.AreEqual("LoadFromCache", value.StringProp); Assert.AreEqual(-1, value.IntProp); }
public void TestInvalidateFromCache() { LoadContext lc = new LoadContext("InvalidateFromCache"); var time = DateTime.Now.ToString(); // write the cache entry // string uniqueName = CacheEntry.BuildUniqueName(typeof(ShortCacheObject), lc); var cii = new CacheItemInfo(uniqueName, DateTime.Now, DateTime.Now.AddHours(1)); DataManager.StoreProvider.Write(cii, ShortCacheObject.SCOLoadRequest.WriteToStream(time, -1).GetBuffer()); Thread.Sleep(250); TestInvalidateCore(lc, time); }
public void TestCleanup() { var dval = DateTime.Now.ToString(); string uniqueName = CacheEntry.BuildUniqueName(typeof(TestPoco), new LoadContext("foo")); DateTime timestamp = DateTime.Now.AddDays(-2); var cii = new CacheItemInfo(uniqueName, timestamp, timestamp); DataManager.StoreProvider.Write(cii, UTF8Encoding.UTF8.GetBytes(dval)); DataManager.Current.Cleanup(DateTime.Now.AddDays(-1), () => { var item = DataManager.StoreProvider.GetLastestExpiringItem(uniqueName); Assert.IsNull(item); TestComplete(); } ); }
private async Task <string> NewCacheStorageForTaskAsync(string taskKey, bool isFolder) { try { string ext = RandomUtils.String(4); var randomName = $"{taskKey}-{ext}"; IStorageItem item = null; if (isFolder) { item = await cacheFolder.CreateFolderAsync( randomName, CreationCollisionOption.GenerateUniqueName); D($"Cache folder created <{item.Path}>"); } else { item = await cacheFolder.CreateFileAsync( randomName, CreationCollisionOption.GenerateUniqueName); D($"Cache file created <{item.Path}>"); } lock (cacheItems) { string token = RandomUtils.String(16); while (cacheItems.ContainsKey(token)) { token = RandomUtils.String(16); } cacheItems[token] = new CacheItemInfo() { Token = token, TaskKey = taskKey, FilePath = item.Path, }; return(token); } } catch (Exception) { return(null); } }
public void TestRefreshBeforeCacheExpires() { IUpdatable val = null; LoadContext lc = new LoadContext(ShortCacheObject.DefaultIdentifier); // write the cache entry // string uniqueName = CacheEntry.BuildUniqueName(typeof(ShortCacheObject), lc); var cii = new CacheItemInfo(uniqueName, DateTime.Now, DateTime.Now.AddHours(1)); var t = DateTime.Now.ToString(); DataManager.StoreProvider.Write(cii, ShortCacheObject.SCOLoadRequest.WriteToStream(t, -1).GetBuffer()); val = DataManager.Current.Load <ShortCacheObject>(lc, (v) => { string oldDefault = ShortCacheObject.DefaultStringValue; // we've got a value Assert.AreEqual(t, v.StringProp); ShortCacheObject.DefaultStringValue = DateTime.Now.ToString(); // now request a new value via refresh. // DataManager.Current.Refresh <ShortCacheObject>(ShortCacheObject.DefaultIdentifier, (v2) => { Assert.AreEqual(v2.StringProp, ShortCacheObject.DefaultStringValue); ShortCacheObject.DefaultStringValue = oldDefault; TestComplete(); }, (ex2) => { Assert.Fail(ex2.Message); TestComplete(); } ); }, (ex) => { Assert.Fail(ex.Message); TestComplete(); }); }
private async Task <CacheItemInfo> GetCacheItemFromDatabaseAsync(string key) { using (var connection = new SqlConnection(_connectionString)) { var command = new SqlCommand( $"SELECT Id, Value, ExpiresAtTime, SlidingExpirationInSeconds, AbsoluteExpiration " + $"FROM {_tableName} WHERE Id = @Id", connection); command.Parameters.AddWithValue("Id", key); await connection.OpenAsync(); var reader = await command.ExecuteReaderAsync(CommandBehavior.SingleRow); // NOTE: The following code is made to run on Mono as well because of which // we cannot use GetFieldValueAsync etc. if (await reader.ReadAsync()) { var cacheItemInfo = new CacheItemInfo { Id = key, Value = (byte[])reader[1], ExpiresAtTime = DateTimeOffset.Parse(reader[2].ToString(), CultureInfo.InvariantCulture) }; if (!await reader.IsDBNullAsync(3)) { cacheItemInfo.SlidingExpirationInSeconds = TimeSpan.FromSeconds(reader.GetInt64(3)); } if (!await reader.IsDBNullAsync(4)) { cacheItemInfo.AbsoluteExpiration = DateTimeOffset.Parse(reader[4].ToString(), CultureInfo.InvariantCulture); } return(cacheItemInfo); } else { return(null); } } }
public override byte[] Read(CacheItemInfo item) { var fi = new FileItem(item); byte[] bytes = null; lock (LockObject) { if (!IsoStore.FileExists(fi.FileName)) { return(null); } using (Stream stream = IsoStore.OpenFile(fi.FileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { bytes = new byte[stream.Length]; stream.Read(bytes, 0, (int)stream.Length); } } return(bytes); }
public void TestWriteAndReadWithoutFlush() { var items = _storeProvider.GetItems("KillMe"); Assert.AreEqual(0, items.Count()); CacheItemInfo cii = new CacheItemInfo("KillMe", DateTime.Now, DateTime.Now.AddHours(1)); _storeProvider.Write(cii, new byte[] { 7 }); Thread.Sleep(100); // let the write happen; var bytes = _storeProvider.Read(cii); Assert.IsNotNull(bytes); Assert.AreEqual(1, bytes.Length); Assert.AreEqual(7, bytes[0]); // cleanup _storeProvider.Delete(cii); }
public override void Delete(CacheItemInfo item) { CacheItemInfo cachedItem; lock (_cache) { if (_cache.TryGetValue(item.UniqueName, out cachedItem) && Object.Equals(item, cachedItem)) { _cache.Remove(item.UniqueName); } } var fi = new FileItem(item); var fileName = fi.FileName; PriorityQueue.AddStorageWorkItem(() => { lock (LockObject) { DeleteFileHelper(IsoStore, fileName); } }); }
public void TestDataLoaderCacheLoad() { var id = "TestPocoCache"; var dval = DateTime.Now.ToString(); string uniqueName = CacheEntry.BuildUniqueName(typeof(TestPoco), new LoadContext(id)); var cii = new CacheItemInfo(uniqueName, DateTime.Now, DateTime.Now.AddSeconds(10)); DataManager.StoreProvider.Write(cii, UTF8Encoding.UTF8.GetBytes(dval)); Thread.Sleep(250); // let the write happen; DataManager.Current.Load <TestPoco>(id, (tp2) => { Assert.AreEqual(dval, tp2.Value); TestComplete(); }, (ex) => { Assert.Fail(); TestComplete(); } ); }
/// <summary> /// Adds or replaces an item in the cache /// </summary> /// <param name="cacheItemInfo"></param> public void Put(CacheItemInfo cacheItemInfo) { ArgumentValidation.NotNull(cacheItemInfo, "entry"); if (!_session.EnsureConnectionIsOpen()) { return; } try { var itemKey = cacheItemInfo.Key.Key.ToLowerInvariant(); var timeout = cacheItemInfo.Key.Profile.GetTimeout(); Task task; if (timeout.HasValue) { task = _session.Connection.Strings.Set(cacheItemInfo.Key.Profile.CacheId, itemKey, SerializationHelper.ProtobufSerialize(cacheItemInfo.Item), (long)timeout.Value.TotalSeconds); } else { task = _session.Connection.Strings.Set(cacheItemInfo.Key.Profile.CacheId, cacheItemInfo.Key.Key.ToLowerInvariant(), SerializationHelper.ProtobufSerialize(cacheItemInfo.Item)); } _session.Connection.Wait(task); } catch (SerializationException e) { throw new ErrorditeCacheException( "Failed to serialize type:={0}, profile:={1}, key:={2}".FormatWith(cacheItemInfo.Item.GetType(), cacheItemInfo.Key.Profile.ProfileName, cacheItemInfo.Key.Key), false, e); } }
private void TestValidCacheCore(string cachedValue, string newValue, string expectedValue, int secondsUntilCacheExpires) { string uniqueName = CacheEntry.BuildUniqueName(typeof(ValidCacheOnlyObject), new LoadContext("VCO")); var cii = new CacheItemInfo(uniqueName, DateTime.Now, DateTime.Now.AddSeconds(secondsUntilCacheExpires)); DataManager.StoreProvider.Write(cii, ShortCacheObject.SCOLoadRequest.WriteToStream(cachedValue, -1).GetBuffer()); Thread.Sleep(100); // sleep to let the write happen; ShortCacheObject.DefaultStringValue = newValue; DataManager.Current.Load <ValidCacheOnlyObject>("VCO", (v1) => { Assert.AreEqual(expectedValue, v1.StringProp); TestComplete(); }, (ex) => { Assert.Fail(); TestComplete(); }); }
/// <summary> /// Updates the sizes of the <see cref="StationaryGrhData"/>s where <see cref="StationaryGrhData.AutomaticSize"/> is set and /// the cached size is invalid. /// </summary> public virtual void UpdateSizes() { // Loop through all StationaryGrhDatas foreach (var gd in GrhInfo.GrhDatas.OfType<StationaryGrhData>()) { // Check that AutomaticSize is set if (!gd.AutomaticSize) continue; // Make sure the asset exists in the dev path var devTexturePath = TryGetAbsoluteFilePath(gd, ContentPaths.Dev); if (devTexturePath == null) continue; // Get the size of the file from the Dev path since we will be needing it later var realFileSize = GetFileSize(devTexturePath); // Check if the GrhData is in the cache CacheItemInfo cacheItem; if (_cache.TryGetValue(gd.GrhIndex, out cacheItem)) { Debug.Assert(gd.GrhIndex == cacheItem.GrhIndex); // The GrhData was in the cache, so check that the cache information is still valid if (gd.Width == cacheItem.Width && gd.Height == cacheItem.Height && gd.TextureName == cacheItem.AssetName && realFileSize == cacheItem.FileSize) { // All of the cached values match the values in the GrhData, so assume its up-to-date and move to the next continue; } } // Make sure the asset exists in the build path var buildTexturePath = TryGetAbsoluteFilePath(gd, ContentPaths.Build); if (buildTexturePath == null) continue; // The GrhData was not in the cache or the cache contains outdated values, so find the real size by grabbing it directly // from the GrhData's texture var realSize = new Vector2(gd.Texture.Width, gd.Texture.Height); // To avoid using too much memory, we will dispose of the texture after we are done. Since the textures are lazy-loaded and // automatically reload, this will not do any harm. We may end up disposing a few textures that were actually being used // right now, but that is not a big deal. gd.Texture.Dispose(); // Set the new size gd.UpdateAutomaticSize(realSize); // Update the cache var addToCache = false; if (cacheItem == null) { cacheItem = new CacheItemInfo(); addToCache = true; } cacheItem.AssetName = gd.TextureName; cacheItem.Width = (int)realSize.X; cacheItem.Height = (int)realSize.Y; cacheItem.GrhIndex = gd.GrhIndex; cacheItem.FileSize = realFileSize; // Since the CacheItemInfo is an object, we only need to add it to the dictionary if it didn't already exist in it if (addToCache) _cache.Add(cacheItem.GrhIndex, cacheItem); } // Be sure to remove any cache items for GrhDatas that no longer exist just to make sure they don't cause any problems // later (and to help remove some storage overhead) var toRemove = new Stack<GrhIndex>(); foreach (var cacheItem in _cache) { if (GrhInfo.GetData(cacheItem.Key) == null) toRemove.Push(cacheItem.Key); } while (toRemove.Count > 0) { var removeGrhIndex = toRemove.Pop(); _cache.Remove(removeGrhIndex); } // Save the cache and the GrhDatas Save(); GrhInfo.Save(ContentPaths.Dev); }
public void Put(CacheItemInfo cacheItem) { _memoryCacheEngine.Put(cacheItem); _redisCacheEngine.Put(cacheItem); }
public FileItem(CacheItemInfo item) { Item = item; }
private static string ToFileName(CacheItemInfo item) { string name = EncodePathName(item.UniqueName); string etag = EncodePathName(item.ETag); name = String.Format("{1}{0}{2}{0}{3}{0}{4}{0}{5}", FileNameSeparator, name, item.IsOptimized, item.ExpirationTime.Ticks, item.UpdatedTime.Ticks, etag); name = Path.Combine(DirectoryHash(item.UniqueName), name); return name; }
public static CacheItemInfo FromFileName(string fileName) { if (!fileName.StartsWith(CacheDirectoryPrefix)) { fileName = Path.GetFileName(fileName); string[] parts = fileName .Split(FileNameSeparator); if (parts.Length == 5) { string uniqueKey = DecodePathName(parts[0]); var item = new CacheItemInfo(uniqueKey) { ExpirationTime = new DateTime(Int64.Parse(parts[2])), UpdatedTime = new DateTime(Int64.Parse(parts[3])), IsOptimized = Boolean.Parse(parts[1]), ETag = DecodePathName(parts[4]) }; return item; } } return null; }
public override void Delete(CacheItemInfo item) { CacheItemInfo cachedItem; lock (_cache) { if (_cache.TryGetValue(item.UniqueName, out cachedItem) && Object.Equals(item, cachedItem)) { _cache.Remove(item.UniqueName); } } var fi = new FileItem(item); var fileName = fi.FileName; Task.Run(() => LocalStorageHelper.DeleteFileInLocalFolderAsync(fileName)); }
public override void Write(CacheItemInfo info, byte[] data) { var fi = new FileItem(info); PriorityQueue.AddStorageWorkItem(() => { lock (LockObject) { for (int r = 0; r < WriteRetries; r++) { try { FileItem.EnsurePath(IsoStore, fi.FileName); using (Stream stream = IsoStore.OpenFile(fi.FileName, FileMode.Create, FileAccess.Write, FileShare.None)) { stream.Write(data, 0, data.Length); stream.Flush(); } _cache[info.UniqueName] = info; break; } catch (IsolatedStorageException ex) { Debug.WriteLine("Exception writing file: Name={0}, Length={1}, {2}", fi.FileName, data.Length, ex.Message); // These IsolatedStorageExceptions seem to happen at random, // haven't yet found a repro. So for the retry, // if we failed, sleep for a bit and then try again. // // SW: I can repro this with a long unique name - originally thought '/' in the name were the cause Thread.Sleep(50); } } } }); }
public void Put(CacheItemInfo cacheItemInfo) { }
public override byte[] Read(CacheItemInfo item) { var fi = new FileItem(item); byte[] bytes = null; lock (LockObject) { if (!IsoStore.FileExists(fi.FileName)) { return null; } using (Stream stream = IsoStore.OpenFile(fi.FileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { bytes = new byte[stream.Length]; stream.Read(bytes, 0, (int)stream.Length); } } return bytes; }
/// <summary> /// Updates the sizes of the <see cref="StationaryGrhData"/>s where <see cref="StationaryGrhData.AutomaticSize"/> is set and /// the cached size is invalid. /// </summary> public virtual void UpdateSizes() { // Loop through all StationaryGrhDatas foreach (var gd in GrhInfo.GrhDatas.OfType <StationaryGrhData>()) { // Check that AutomaticSize is set if (!gd.AutomaticSize) { continue; } // Make sure the asset exists in the dev path var devTexturePath = TryGetAbsoluteFilePath(gd, ContentPaths.Dev); if (devTexturePath == null) { continue; } // Get the size of the file from the Dev path since we will be needing it later var realFileSize = GetFileSize(devTexturePath); // Check if the GrhData is in the cache CacheItemInfo cacheItem; if (_cache.TryGetValue(gd.GrhIndex, out cacheItem)) { Debug.Assert(gd.GrhIndex == cacheItem.GrhIndex); // The GrhData was in the cache, so check that the cache information is still valid if (gd.Width == cacheItem.Width && gd.Height == cacheItem.Height && gd.TextureName == cacheItem.AssetName && realFileSize == cacheItem.FileSize) { // All of the cached values match the values in the GrhData, so assume its up-to-date and move to the next continue; } } // Make sure the asset exists in the build path var buildTexturePath = TryGetAbsoluteFilePath(gd, ContentPaths.Build); if (buildTexturePath == null) { continue; } // The GrhData was not in the cache or the cache contains outdated values, so find the real size by grabbing it directly // from the GrhData's texture var realSize = new Vector2(gd.Texture.Width, gd.Texture.Height); // To avoid using too much memory, we will dispose of the texture after we are done. Since the textures are lazy-loaded and // automatically reload, this will not do any harm. We may end up disposing a few textures that were actually being used // right now, but that is not a big deal. gd.Texture.Dispose(); // Set the new size gd.UpdateAutomaticSize(realSize); // Update the cache var addToCache = false; if (cacheItem == null) { cacheItem = new CacheItemInfo(); addToCache = true; } cacheItem.AssetName = gd.TextureName; cacheItem.Width = (int)realSize.X; cacheItem.Height = (int)realSize.Y; cacheItem.GrhIndex = gd.GrhIndex; cacheItem.FileSize = realFileSize; // Since the CacheItemInfo is an object, we only need to add it to the dictionary if it didn't already exist in it if (addToCache) { _cache.Add(cacheItem.GrhIndex, cacheItem); } } // Be sure to remove any cache items for GrhDatas that no longer exist just to make sure they don't cause any problems // later (and to help remove some storage overhead) var toRemove = new Stack <GrhIndex>(); foreach (var cacheItem in _cache) { if (GrhInfo.GetData(cacheItem.Key) == null) { toRemove.Push(cacheItem.Key); } } while (toRemove.Count > 0) { var removeGrhIndex = toRemove.Pop(); _cache.Remove(removeGrhIndex); } // Save the cache and the GrhDatas Save(); GrhInfo.Save(ContentPaths.Dev); }
public override void Write(CacheItemInfo info, byte[] data) { var fi = new FileItem(info); PriorityQueue.AddStorageWorkItem(async () => { await FileItem.EnsurePathAsync(fi.FileName); await LocalStorageHelper.WriteStreamToFileInLocalFolderAsync(fi.FileName, data); }); }
public override byte[] Read(CacheItemInfo item) { var fi = new FileItem(item); byte[] bytes = null; bool fileExists = Task.Run(() => LocalStorageHelper.FileExistsInLocalFolderAsync(fi.FileName)).Result; if (!fileExists) return null; Stream stream = Task.Run(() => LocalStorageHelper.ReadStreamFromFileInLocalFolderAsync(fi.FileName)).Result; bytes = new byte[stream.Length]; stream.Read(bytes, 0, (int)stream.Length); return bytes; }
public override IEnumerable <CacheItemInfo> GetItems(string uniqueName) { CacheItemInfo item; if (_cache.TryGetValue(uniqueName, out item)) { return(new CacheItemInfo[] { item }); } // find the directory. // var dir = FileItem.DirectoryHash(uniqueName); if (IsoStore.DirectoryExists(dir)) { lock (LockObject) { string[] files = null; try { files = IsoStore.GetFileNames(dir + "\\*"); } catch (IsolatedStorageException) { // intermittent IsoStore exceptions on shutdown. files = new string[0]; } List <CacheItemInfo> items = new List <CacheItemInfo>(); foreach (var f in files) { CacheItemInfo cii = FileItem.FromFileName(f); if (cii != null) { items.Add(cii); } } var orderedItems = from i in items where i.UniqueName == uniqueName orderby i.ExpirationTime descending select i; foreach (var i in orderedItems) { if (item == null) { item = i; continue; } Delete(i); } if (item != null) { _cache[uniqueName] = item; return(new CacheItemInfo[] { item }); } } } return(new CacheItemInfo[0]); }
public override void Update(CacheItemInfo oldInfo, CacheItemInfo newInfo) { if (oldInfo.Equals(newInfo)) return; var oldFilename = new FileItem(oldInfo).FileName; var newFilename = new FileItem(newInfo).FileName; PriorityQueue.AddStorageWorkItem(() => { lock (LockObject) { using (var store = IsolatedStorageFile.GetUserStoreForApplication()) { if (store.FileExists(newFilename)) store.DeleteFile(newFilename); using (var readStream = new IsolatedStorageFileStream(oldFilename, FileMode.Open, store)) using (var writeStream = new IsolatedStorageFileStream(newFilename, FileMode.Create, store)) using (var reader = new StreamReader(readStream)) using (var writer = new StreamWriter(writeStream)) { writer.Write(reader.ReadToEnd()); } store.DeleteFile(oldFilename); } } }); }