/// <summary> /// 获取文件缓存,失败时创建缓存对象 /// </summary> /// <param name="path"></param> /// <param name="fileCache"></param> /// <param name="isCopyPath">是否复制请求路径</param> /// <returns>是否新的文件缓存数据</returns> private byte get(ref FileCacheKey path, out FileCache fileCache, bool isCopyPath) { byte isNewFileCache = 0; Monitor.Enter(fileLock); if ((fileCache = files.Get(ref path, null)) == null) { byte isLock = 0; try { fileCache = new FileCache(); isLock = 1; if (isCopyPath) { path.CopyPath(); } files.UnsafeAdd(ref path, fileCache); return(isNewFileCache = 1); } finally { Monitor.Exit(fileLock); if (isNewFileCache == 0 && isLock != 0) { fileCache.PulseAll(); } } } else { Monitor.Exit(fileLock); } return(0); }
/// <summary> /// 设置缓存数据 /// </summary> /// <param name="index"></param> /// <param name="data"></param> internal void SetCache(long index, byte[] data) { if (DataCache == null) { IndexCache.UnsafeAdd(ref index, new HashBytes { SubArray = new SubArray <byte> { Array = data } }); if ((freeCacheSize -= data.Length) < 0) { HashBytes removeData; do { removeData = IndexCache.UnsafePopValue(); }while ((freeCacheSize += removeData.SubArray.Array.Length) < 0); } } else { HashBytes hashData = data; Dictionary <HashBytes, DataCache> cache = DataCache[hashData.HashCode & 0xff]; if (cache == null) { IndexCache.UnsafeAdd(ref index, hashData); freeCacheSize -= data.Length; DataCache[hashData.HashCode & 0xff] = cache = DictionaryCreator.CreateHashBytes <DataCache>(); cache.Add(hashData, new DataCache { Data = hashData, Index = index, Count = 1 }); } else { DataCache count; if (cache.TryGetValue(hashData, out count)) { IndexCache.UnsafeAdd(ref index, count.Data); ++count.Count; freeCacheSize -= data.Length; cache[hashData] = count; } else { IndexCache.UnsafeAdd(ref index, hashData); freeCacheSize -= data.Length; cache.Add(hashData, new DataCache { Data = hashData, Index = index, Count = 1 }); } } DataCache removeData; while (freeCacheSize < 0) { removeData.Data = IndexCache.UnsafePopValue(); freeCacheSize += removeData.Data.SubArray.Array.Length; cache = DataCache[removeData.Data.HashCode & 0xff]; if (cache != null && cache.TryGetValue(removeData.Data, out removeData)) { if (--removeData.Count == 0) { cache.Remove(removeData.Data); } else { cache[removeData.Data] = removeData; } } } } }
/// <summary> /// 日志写入 /// </summary> private void output() { DebugInfo value = null; FileStreamWriter fileStream; do { while (System.Threading.Interlocked.CompareExchange(ref debugLock, 1, 0) != 0) { AutoCSer.Threading.ThreadYield.Yield(AutoCSer.Threading.ThreadYield.Type.FileLogExchangeDebug); } if (newDebugs.IsEmpty) { System.Threading.Interlocked.Exchange(ref debugLock, 0); return; } debugs.Exchange(ref newDebugs); System.Threading.Interlocked.Exchange(ref debugLock, 0); do { try { while ((value = debugs.PopOnly()) != null) { switch (value.CacheType) { case CacheType.Queue: HashString cacheKey = value.ToString(); if (cache.Get(ref cacheKey, false)) { fileStream = null; } else { cache.UnsafeAdd(ref cacheKey, true); if (cache.Count > maxCacheCount) { cache.UnsafePopNode(); } fileStream = this.fileStream; } break; case CacheType.Last: HashString key = value.ToString(); if (key.Equals(ref lastCache)) { fileStream = null; } else { lastCache = key; fileStream = this.fileStream; } break; default: fileStream = this.fileStream; break; } if (fileStream != null) { if (value.Type == LogType.Flush) { fileStream.Flush(); } else { string log = @" " + Date.NowTime.Now.toString() + " : " + value.ToString() + @" "; #if XAMARIN Trace.Console(log); if (fileStream.WriteNotEmpty(log) != -1 && (value.Type & LogType.Flush) != 0) { fileStream.Flush(); } #else if (fileStream.WriteNotEmpty(log) >= MaxSize && MaxSize > 0) { moveBak(); } else if ((value.Type & LogType.Flush) != 0) { fileStream.Flush(); } #endif } } pulseWait(value); } goto END; } catch { pulseWait(value); CatchCount.Add(CatchCount.Type.Log_Output); } }while (true); END: debugs.SetHeaderNextNull(); }while (true); }