private void ReReadBuffer(LogBuffer logBuffer) { #if DEBUG Logger.logInfo(string.Format("re-reading buffer: {0}/{1}/{2}", logBuffer.StartLine, logBuffer.LineCount, logBuffer.FileInfo.FullName)); #endif try { Monitor.Enter(logBuffer); Stream fileStream = null; try { fileStream = logBuffer.FileInfo.OpenStream(); } catch (IOException e) { Logger.logWarn(e); return; } try { ILogStreamReader reader = GetLogStreamReader(fileStream, EncodingOptions, UseNewReader); string line; long filePos = logBuffer.StartPos; reader.Position = logBuffer.StartPos; int maxLinesCount = logBuffer.LineCount; int lineCount = 0; int dropCount = logBuffer.PrevBuffersDroppedLinesSum; logBuffer.ClearLines(); while (ReadLine(reader, logBuffer.StartLine + logBuffer.LineCount, logBuffer.StartLine + logBuffer.LineCount + dropCount, out line)) { if (lineCount >= maxLinesCount) { break; } if (line == null) { dropCount++; continue; } logBuffer.AddLine(line, filePos); filePos = reader.Position; lineCount++; } if (maxLinesCount != logBuffer.LineCount) { Logger.logWarn(string.Format("LineCount in buffer differs after re-reading. old={0}, new={1}", maxLinesCount, logBuffer.LineCount)); } if (dropCount - logBuffer.PrevBuffersDroppedLinesSum != logBuffer.DroppedLinesCount) { Logger.logWarn(string.Format("DroppedLinesCount in buffer differs after re-reading. old={0}, new={1}", logBuffer.DroppedLinesCount, dropCount)); logBuffer.DroppedLinesCount = dropCount - logBuffer.PrevBuffersDroppedLinesSum; } GC.KeepAlive(fileStream); } catch (IOException e) { Logger.logWarn(e); } finally { fileStream.Close(); } } finally { Monitor.Exit(logBuffer); } }
private void UpdateLruCache(LogBuffer logBuffer) { LogBufferCacheEntry cacheEntry; _lruCacheDictLock.AcquireReaderLock(Timeout.Infinite); if (_lruCacheDict.TryGetValue(logBuffer.StartLine, out cacheEntry)) { cacheEntry.Touch(); } else { LockCookie cookie = _lruCacheDictLock.UpgradeToWriterLock(Timeout.Infinite); if (!_lruCacheDict.TryGetValue(logBuffer.StartLine, out cacheEntry)) // #536: re-test, because multiple threads may have been waiting for writer lock { cacheEntry = new LogBufferCacheEntry(); cacheEntry.LogBuffer = logBuffer; try { _lruCacheDict.Add(logBuffer.StartLine, cacheEntry); } catch (ArgumentException e) { #if DEBUG // there seems to be a bug with double added key Logger.logError(string.Format("Error in LRU cache: {0}", e.Message)); Logger.logInfo("Added buffer:"); DumpBufferInfos(logBuffer); LogBufferCacheEntry exisingEntry; if (_lruCacheDict.TryGetValue(logBuffer.StartLine, out exisingEntry)) { Logger.logInfo("Existing buffer: "); DumpBufferInfos(exisingEntry.LogBuffer); } else { Logger.logWarn("Ooops? Cannot find the already existing entry in LRU."); } #endif _lruCacheDictLock.ReleaseLock(); throw e; } } _lruCacheDictLock.DowngradeFromWriterLock(ref cookie); } _lruCacheDictLock.ReleaseReaderLock(); }
/// <summary> /// Sets a new start line in the given buffer and updates the LRU cache, if the buffer /// is present in the cache. The caller must have write lock for 'lruCacheDictLock'; /// </summary> /// <param name="logBuffer"></param> /// <param name="newLineNum"></param> private void SetNewStartLineForBuffer(LogBuffer logBuffer, int newLineNum) { Util.AssertTrue(_lruCacheDictLock.IsWriterLockHeld, "No writer lock for lru cache"); if (_lruCacheDict.ContainsKey(logBuffer.StartLine)) { _lruCacheDict.Remove(logBuffer.StartLine); logBuffer.StartLine = newLineNum; LogBufferCacheEntry cacheEntry = new LogBufferCacheEntry(); cacheEntry.LogBuffer = logBuffer; _lruCacheDict.Add(logBuffer.StartLine, cacheEntry); } else { logBuffer.StartLine = newLineNum; } }
private void AddBufferToList(LogBuffer logBuffer) { #if DEBUG Logger.logDebug(string.Format("AddBufferToList(): {0}/{1}/{2}", logBuffer.StartLine, logBuffer.LineCount, logBuffer.FileInfo.FullName)); #endif _bufferList.Add(logBuffer); //UpdateLru(logBuffer); UpdateLruCache(logBuffer); }
private void ReadToBufferList(ILogFileInfo logFileInfo, long filePos, int startLine) { #if DEBUG //Logger.logDebug("ReadToBufferList(): " + ILogFileInfo.FileName + ", filePos " + filePos + ", startLine: " + startLine); #endif Stream fileStream; ILogStreamReader reader = null; try { fileStream = logFileInfo.OpenStream(); bool canSeek = fileStream.CanSeek; } catch (IOException fe) { Logger.logWarn(string.Format("IOException: {0}", fe.ToString())); _isDeleted = true; LineCount = 0; _currFileSize = 0; OnFileNotFound(); // notify LogWindow return; } try { reader = GetLogStreamReader(fileStream, EncodingOptions, UseNewReader); reader.Position = filePos; _fileLength = logFileInfo.Length; String line; int lineNum = startLine; LogBuffer logBuffer; AcquireBufferListReaderLock(); if (_bufferList.Count == 0) { logBuffer = new LogBuffer(logFileInfo, MAX_LINES_PER_BUFFER); logBuffer.StartLine = startLine; logBuffer.StartPos = filePos; LockCookie cookie = UpgradeBufferListLockToWriter(); AddBufferToList(logBuffer); DowngradeBufferListLockFromWriter(ref cookie); #if DEBUG //Logger.logDebug("ReadToBufferList(): new buffer created"); #endif } else { logBuffer = _bufferList[_bufferList.Count - 1]; //if (logBuffer.FileInfo != ILogFileInfo) if (!logBuffer.FileInfo.FullName.Equals(logFileInfo.FullName)) { logBuffer = new LogBuffer(logFileInfo, MAX_LINES_PER_BUFFER); logBuffer.StartLine = startLine; logBuffer.StartPos = filePos; LockCookie cookie = UpgradeBufferListLockToWriter(); AddBufferToList(logBuffer); DowngradeBufferListLockFromWriter(ref cookie); #if DEBUG //Logger.logDebug("ReadToBufferList(): new buffer created because new ILogFileInfo"); #endif } _disposeLock.AcquireReaderLock(Timeout.Infinite); if (logBuffer.IsDisposed) { LockCookie cookie = _disposeLock.UpgradeToWriterLock(Timeout.Infinite); ReReadBuffer(logBuffer); _disposeLock.DowngradeFromWriterLock(ref cookie); } _disposeLock.ReleaseReaderLock(); } Monitor.Enter(logBuffer); // Lock the buffer ReleaseBufferListReaderLock(); int lineCount = logBuffer.LineCount; int droppedLines = logBuffer.PrevBuffersDroppedLinesSum; filePos = reader.Position; while (ReadLine(reader, logBuffer.StartLine + logBuffer.LineCount, logBuffer.StartLine + logBuffer.LineCount + droppedLines, out line)) { if (_shouldStop) { Monitor.Exit(logBuffer); return; } if (line == null) { logBuffer.DroppedLinesCount = logBuffer.DroppedLinesCount + 1; droppedLines++; continue; } lineCount++; if (lineCount > MAX_LINES_PER_BUFFER && reader.IsBufferComplete) { OnLoadFile(new LoadFileEventArgs(logFileInfo.FullName, filePos, false, logFileInfo.Length, false)); #if DEBUG //Logger.logDebug("ReadToBufferList(): new buffer created. lineCount: " + lineCount + ", lineNum:" + lineNum + ", text: " + line); #endif //logBuffer.Size = filePos - logBuffer.StartPos; Monitor.Exit(logBuffer); logBuffer = new LogBuffer(logFileInfo, MAX_LINES_PER_BUFFER); Monitor.Enter(logBuffer); logBuffer.StartLine = lineNum; logBuffer.StartPos = filePos; logBuffer.PrevBuffersDroppedLinesSum = droppedLines; AcquireBufferListWriterLock(); AddBufferToList(logBuffer); ReleaseBufferListWriterLock(); lineCount = 1; } logBuffer.AddLine(line, filePos); filePos = reader.Position; lineNum++; } logBuffer.Size = filePos - logBuffer.StartPos; Monitor.Exit(logBuffer); _isLineCountDirty = true; _currFileSize = reader.Position; CurrentEncoding = reader.Encoding; // Reader may have detected another encoding if (!_shouldStop) { OnLoadFile(new LoadFileEventArgs(logFileInfo.FullName, filePos, true, _fileLength, false)); // Fire "Ready" Event } GC.KeepAlive(fileStream); } catch (IOException ioex) { Logger.logWarn(string.Format("{0}: {1}", ioex.GetType().Name, ioex.Message)); } finally { fileStream.Close(); } }
/// <summary> /// The caller must have writer locks for lruCache and buffer list! /// </summary> /// <param name="buffer"></param> private void RemoveFromBufferList(LogBuffer buffer) { Util.AssertTrue(_lruCacheDictLock.IsWriterLockHeld, "No writer lock for lru cache"); Util.AssertTrue(_bufferListLock.IsWriterLockHeld, "No writer lock for buffer list"); _lruCacheDict.Remove(buffer.StartLine); _bufferList.Remove(buffer); }
private void DumpBufferInfos(LogBuffer buffer) { Logger.logInfo(string.Format("StartLine: {0}", buffer.StartLine)); Logger.logInfo(string.Format("LineCount: {0}", buffer.LineCount)); Logger.logInfo(string.Format("StartPos: {0}", buffer.StartPos)); Logger.logInfo(string.Format("Size: {0}", buffer.Size)); Logger.logInfo(string.Format("Disposed: {0}", buffer.IsDisposed ? "yes" : "no")); Logger.logInfo(string.Format("DisposeCount: {0}", buffer.DisposeCount)); Logger.logInfo(string.Format("File: {0}", buffer.FileInfo.FullName)); }
private LogBuffer GetFirstBufferForFileByLogBuffer(LogBuffer logBuffer) { ILogFileInfo info = logBuffer.FileInfo; AcquireBufferListReaderLock(); int index = _bufferList.IndexOf(logBuffer); if (index == -1) { ReleaseBufferListReaderLock(); return null; } LogBuffer resultBuffer = logBuffer; while (true) { index--; if (index < 0 || _bufferList[index].FileInfo != info) { break; } resultBuffer = _bufferList[index]; } ReleaseBufferListReaderLock(); return resultBuffer; }