/// <inheritdoc /> public bool HasAssetOrDependencyChanged(CachedInfo info) { if (info == null || !info.Asset.IsValid() || info.Asset != GetUpdatedCacheEntry(info.Asset)) return true; foreach (var dependency in info.Dependencies) { if (!dependency.IsValid() || dependency != GetUpdatedCacheEntry(dependency)) return true; } return false; }
/// <inheritdoc /> public bool NeedsRebuild(CachedInfo info) { if (info == null || !info.Asset.IsValid() || info.Asset != GetUpdatedCacheEntry(info.Asset)) { return(true); } foreach (var dependency in info.Dependencies) { if (!dependency.IsValid() || dependency != GetUpdatedCacheEntry(dependency)) { return(true); } } return(false); }
/// <inheritdoc /> public bool HasAssetOrDependencyChanged(CachedInfo info) { if (info == null || !info.Asset.IsValid()) { return(true); } var result = false; var updatedEntry = GetUpdatedCacheEntry(info.Asset); if (info.Asset != updatedEntry) { if (!LogCacheMiss($"[Cache Miss]: Source asset changed. Old: {info.Asset} New: {updatedEntry}")) { return(true); } result = true; } foreach (var dependency in info.Dependencies) { if (!dependency.IsValid()) { if (!LogCacheMiss($"[Cache Miss]: Dependency is no longer valid. Asset: {info.Asset} Dependency: {dependency}")) { return(true); } result = true; } updatedEntry = GetUpdatedCacheEntry(dependency); if (dependency != GetUpdatedCacheEntry(updatedEntry)) { if (!LogCacheMiss($"[Cache Miss]: Dependency changed. Asset: {info.Asset} Old: {dependency} New: {updatedEntry}")) { return(true); } result = true; } } return(result); }
/// <inheritdoc /> public void LoadCachedData(IList <CacheEntry> entries, out IList <CachedInfo> cachedInfos) { if (entries == null) { cachedInfos = null; return; } if (entries.Count == 0) { cachedInfos = new List <CachedInfo>(); return; } // Setup Operations var ops = new FileOperations(entries.Count); for (int i = 0; i < entries.Count; i++) { var op = ops.data[i]; op.file = GetCachedInfoFile(entries[i]); ops.data[i] = op; } // Start file reading Thread thread = new Thread(Read); thread.Start(ops); cachedInfos = new List <CachedInfo>(entries.Count); // Deserialize as files finish reading var formatter = new BinaryFormatter(); for (int index = 0; index < entries.Count; index++) { // Basic wait lock ops.waitLock.WaitOne(); CachedInfo info = null; try { var op = ops.data[index]; if (op.bytes != null && op.bytes.Length > 0) { info = formatter.Deserialize(op.bytes) as CachedInfo; } } catch (Exception e) { BuildLogger.LogException(e); } cachedInfos.Add(info); } thread.Join(); ((IDisposable)ops.waitLock).Dispose(); // Validate cached data is reusable for (int i = 0; i < cachedInfos.Count; i++) { if (HasAssetOrDependencyChanged(cachedInfos[i])) { cachedInfos[i] = null; } } // If we have a cache server connection, download & check any missing info if (m_Downloader != null) { m_Downloader.DownloadMissing(entries, cachedInfos); } Assert.AreEqual(entries.Count, cachedInfos.Count); }
/// <inheritdoc /> public void LoadCachedData(IList <CacheEntry> entries, out IList <CachedInfo> cachedInfos) { if (entries == null) { cachedInfos = null; return; } if (entries.Count == 0) { cachedInfos = new List <CachedInfo>(); return; } using (m_Logger.ScopedStep(LogLevel.Info, "LoadCachedData")) { m_Logger.AddEntrySafe(LogLevel.Info, $"{entries.Count} items"); // Setup Operations var ops = new FileOperations(entries.Count); using (m_Logger.ScopedStep(LogLevel.Info, "GetCachedInfoFile")) { for (int i = 0; i < entries.Count; i++) { var op = ops.data[i]; op.file = GetCachedInfoFile(entries[i]); ops.data[i] = op; } } int cachedCount = 0; using (m_Logger.ScopedStep(LogLevel.Info, "Read and deserialize cache info")) { // Start file reading Thread thread = new Thread(Read); thread.Start(ops); cachedInfos = new List <CachedInfo>(entries.Count); // Deserialize as files finish reading Stopwatch deserializeTimer = Stopwatch.StartNew(); var formatter = new BinaryFormatter(); for (int index = 0; index < entries.Count; index++) { // Basic wait lock if (!ops.waitLock.WaitOne(0)) { deserializeTimer.Stop(); ops.waitLock.WaitOne(); deserializeTimer.Start(); } CachedInfo info = null; try { var op = ops.data[index]; if (op.bytes != null && op.bytes.Length > 0) { info = formatter.Deserialize(op.bytes) as CachedInfo; cachedCount++; } else { LogCacheMiss($"[Cache Miss]: Missing cache entry. Entry: {entries[index]}"); } } catch (Exception e) { BuildLogger.LogException(e); } cachedInfos.Add(info); } thread.Join(); ((IDisposable)ops.waitLock).Dispose(); deserializeTimer.Stop(); m_Logger.AddEntrySafe(LogLevel.Info, $"Time spent deserializing: {deserializeTimer.ElapsedMilliseconds}ms"); m_Logger.AddEntrySafe(LogLevel.Info, $"Local Cache hit count: {cachedCount}"); } using (m_Logger.ScopedStep(LogLevel.Info, "Check for changed dependencies")) { for (int i = 0; i < cachedInfos.Count; i++) { if (HasAssetOrDependencyChanged(cachedInfos[i])) { cachedInfos[i] = null; } } } // If we have a cache server connection, download & check any missing info int downloadedCount = 0; if (m_Downloader != null) { using (m_Logger.ScopedStep(LogLevel.Info, "Download Missing Entries")) { m_Downloader.DownloadMissing(entries, cachedInfos); downloadedCount = cachedInfos.Count(i => i != null) - cachedCount; } } m_Logger.AddEntrySafe(LogLevel.Info, $"Local Cache hit count: {cachedCount}, Cache Server hit count: {downloadedCount}"); Assert.AreEqual(entries.Count, cachedInfos.Count); } }