/// <summary>Removes entries from the cache until the total cache size is below the given value.</summary> private static void TrimCacheToMaxSize(uint maxSize) { uint trimmedSize = RequestCache.currentCacheSize; int lastIndex; for (lastIndex = 0; lastIndex < RequestCache.responses.Count && trimmedSize > maxSize; ++lastIndex) { trimmedSize -= RequestCache.responses[lastIndex].size; } if (trimmedSize > 0) { RequestCache.RemoveOldestEntries(lastIndex + 1); } else { RequestCache.Clear(); } }
/// <summary>Stores a response in the cache.</summary> public static void StoreResponse(string url, string responseBody) { if (LocalUser.OAuthToken != RequestCache.lastOAuthToken) { RequestCache.Clear(); RequestCache.lastOAuthToken = LocalUser.OAuthToken; } if (string.IsNullOrEmpty(url)) { Debug.LogWarning("[mod.io] Attempted to cache response for null or empty URL."); return; } Entry entry = new Entry() { timeStamp = ServerTimeStamp.Now, responseBody = responseBody, }; RequestCache.storedResponses[url] = entry; }
/// <summary>Removes the oldest entries from the cache.</summary> private static void RemoveOldestEntries(int count) { Debug.Assert(count > 0); // check if clearing all if (count >= RequestCache.responses.Count) { RequestCache.Clear(); return; } // update url map List <string> urlKeys = new List <string>(RequestCache.urlResponseIndexMap.Keys); foreach (string url in urlKeys) { int newValue = RequestCache.urlResponseIndexMap[url] - count; RequestCache.urlResponseIndexMap[url] = newValue; if (newValue < 0) { RequestCache.urlResponseIndexMap.Remove(url); } } // update cache size uint sizeToRemove = 0; for (int i = 0; i < count; ++i) { sizeToRemove += RequestCache.responses[i].size; } RequestCache.currentCacheSize -= sizeToRemove; // remove responses RequestCache.responses.RemoveRange(0, count); }
/// <summary>Stores a response in the cache.</summary> public static void StoreResponse(string url, string responseBody) { if (LocalUser.OAuthToken != RequestCache.lastOAuthToken) { RequestCache.Clear(); RequestCache.lastOAuthToken = LocalUser.OAuthToken; } string endpointURL = null; // try to remove the apiURL if (!RequestCache.TryTrimAPIURLAndKey(url, out endpointURL)) { Debug.LogWarning("[mod.io] Attempted to cache response for url that does not contain the api URL." + "\nRequest URL: " + (url == null ? "NULL" : url)); return; } // remove stale entry int oldIndex; Entry oldValue; if (RequestCache.TryGetEntry(endpointURL, out oldIndex, out oldValue)) { Debug.LogWarning("[mod.io] Stale cached request found. Removing all older entries."); RequestCache.RemoveOldestEntries(oldIndex + 1); } // calculate new entry size uint size = 0; if (responseBody != null) { size = (uint)responseBody.Length * sizeof(char); } // trim cache if necessary if (size > RequestCache.MAX_CACHE_SIZE) { Debug.Log("[mod.io] Could not cache entry as the response body is larger than MAX_CACHE_SIZE." + "\nMAX_CACHE_SIZE=" + ValueFormatting.ByteCount(RequestCache.MAX_CACHE_SIZE, "0.0") + "\nendpointURL=" + endpointURL + "\nResponseBody Size=" + ValueFormatting.ByteCount(size, "0.0")); return; } if (RequestCache.currentCacheSize + size > RequestCache.MAX_CACHE_SIZE) { RequestCache.TrimCacheToMaxSize(RequestCache.MAX_CACHE_SIZE - size); } // add new entry Entry newValue = new Entry() { timeStamp = ServerTimeStamp.Now, responseBody = responseBody, size = size, }; RequestCache.urlResponseIndexMap.Add(endpointURL, RequestCache.responses.Count); RequestCache.responses.Add(newValue); RequestCache.currentCacheSize += size; }
/// <summary>Stores a collection of mods in the response cache.</summary> public static void StoreMods(int gameId, IEnumerable <ModProfile> mods) { if (mods == null) { return; } List <string> endpointList = new List <string>(); List <Entry> entryList = new List <Entry>(); int now = ServerTimeStamp.Now; uint culmativeSize = 0; foreach (var mod in mods) { if (mod != null) { string endpointURL = APIClient.BuildGetModEndpointURL(gameId, mod.id); // skip if already cached if (RequestCache.urlResponseIndexMap.ContainsKey(endpointURL)) { continue; } string modJSON = JsonConvert.SerializeObject(mod); uint size = (uint)modJSON.Length * sizeof(char); // break out if size is greater than max cache size if (culmativeSize + size >= RequestCache.MAX_CACHE_SIZE) { break; } else { endpointList.Add(endpointURL); entryList.Add(new Entry() { timeStamp = now, size = size, responseBody = modJSON, }); culmativeSize += size; } } } // early out if no mods to add if (culmativeSize == 0) { return; } // make space in cache if (culmativeSize + RequestCache.currentCacheSize > RequestCache.MAX_CACHE_SIZE) { RequestCache.TrimCacheToMaxSize(RequestCache.MAX_CACHE_SIZE - culmativeSize); } // add entries int indexBase = RequestCache.responses.Count; for (int i = 0; i < endpointList.Count; ++i) { RequestCache.urlResponseIndexMap.Add(endpointList[i], i + indexBase); } RequestCache.responses.AddRange(entryList); RequestCache.currentCacheSize += culmativeSize; }