// This is called when reading the circular part of the log to // double check that we have a valid record. private static bool FlagsAreValid(DataFlags flags) { if ((flags & DataFlags.InvalidOnes) != DataFlags.None) { return(false); } if ((flags & DataFlags.CircularStart) != DataFlags.None) { // Circular flag should never appear twice. return(false); } if ((flags & DataFlags.LineNumber) != DataFlags.None) { // LineNumber should never be set in the circular because // every record has a record in the circular part includes the line number. return(false); } if ((flags & DataFlags.MethodEntry) == DataFlags.MethodEntry && (flags & DataFlags.MethodExit) == DataFlags.MethodExit) { // These two should never appear together. return(false); } return(true); }
public Record(DataFlags dataflags, uint msgNum, DateTime time, ReaderThreadInfo threadInfo, string msg) { MsgNum = msgNum; Time = time; Thread = threadInfo.Thread; ThreadName = threadInfo.ThreadName; Level = threadInfo.Level; Logger = threadInfo.Logger; StackDepth = threadInfo.Depth; MethodName = threadInfo.MethodName; if ((dataflags & DataFlags.MethodEntry) != DataFlags.None) { // This is a method entry record. It always contains exactly one line of text. IsEntry = true; Lines = new string[] { string.Format("{{{0}: entered", MethodName) }; } else if ((dataflags & DataFlags.MethodExit) != DataFlags.None) { // Method exit records always contain exactly one line of text. Lines = new string[] { string.Format("}}{0}: exiting", MethodName) }; } else { // The message text for this record may contain newlines. Split the // message into one or more lines. Lines = msg.Split(_splitArg); IsCollapsed = Lines.Length > 1 && !Settings1.Default.ExpandNewlines; } // Each line also has a bool to indicate if it is bookmarked // and a row index it may map to. IsBookmarked = new bool[Lines.Length]; RowIndices = new int[Lines.Length]; }
// Resets all state data that might be associated with an earlier binary file // and prepares for the next (specified) opening of the file. internal void ResetBinaryFileStateData(int fileNum, DataFlags flags) { BinaryFileState.LastFileNumber = fileNum; BinaryFileState.LastTraceLevel = TraceLevel.Off; BinaryFileState.LastThreadName = null; BinaryFileState.LastMethod = string.Empty; BinaryFileState.LastLogger = null; BinaryFileState.LastBlock = 0; // For simplicity, abandon the stack rather than deal with the fact that there // may be a deep call stack when the file is closed and reopened. BinaryFileState.StackDepth = 0; for (StackEntry stackEntry = TopStackEntry; stackEntry != null; stackEntry = stackEntry.Caller) { if (stackEntry.BinaryFileState == BinaryFileState) { stackEntry.Destinations &= ~Destinations.BinaryFile; stackEntry.BinaryFileState = null; } } // I'm not sure why we wouldn't always do this. if ((flags & DataFlags.MethodEntry) == 0) { BinaryFileState.CurrentMethod = string.Empty; } }
/// <summary> /// Creates new instance. /// </summary> /// <param name="buffer">Buffer.</param> /// <param name="offset">Offset.</param> /// <param name="size">Size.</param> /// <param name="flags">Flags.</param> public SentReceivedEventArgs(byte[] buffer, int offset, int size, DataFlags flags) { Buffer = buffer ?? throw new ArgumentNullException(nameof(buffer)); DataOffset = offset; DataSize = size; DataFlags = flags; }
// Gets the DataFlags for next record, possibly entering the circular part of the log. // Returns DataFlags.None or throws an exception if the last record has been read. // Used in file format version 5-. private DataFlags GetFlags(out ulong thisRecNum) { DataFlags flags = DataFlags.None; bool firstCircularRecord = false; thisRecNum = LastRecordNum + 1; // for now if (_circularStartPos == 0) { // Not in circular part yet flags = (DataFlags)_fileReader.ReadUInt16(); _reader.BytesRead += sizeof(DataFlags); if ((flags & DataFlags.CircularStart) != DataFlags.None) { BeginCircular(); // Will set _circularStartPos to non-zero. firstCircularRecord = true; } } if (_circularStartPos != 0) { // We're in the circular part, where every record starts with its // UInt32 record number, before the data flags. thisRecNum = _fileReader.ReadUInt32(); _reader.BytesRead += sizeof(UInt32); if (firstCircularRecord) { // This is the first chronological record in the circular part, // so accept the record number as-is. flags = (DataFlags)_fileReader.ReadUInt16(); _reader.BytesRead += sizeof(DataFlags); } else { // thisRecNum must equal _recordNumber + 1 or we've read past the last record. // If it's a good record, we need to increment _recordNumber. if (thisRecNum == LastRecordNum + 1) { flags = (DataFlags)_fileReader.ReadUInt16(); _reader.BytesRead += sizeof(DataFlags); // There's a slim chance we a read random data that contained the expected // value. Therefore, also check for invalid flags. if (!FlagsAreValid(flags)) { flags = DataFlags.None; } } else { // We've already read the last (newest) record, and now we're reading garbage. flags = DataFlags.None; } } } return(flags); }
/// <summary> /// Copies mesh data from one native array to another /// </summary> public static bool CopyNativeDataToMesh(NativeMeshData from, Mesh to, DataFlags dataFlags) { if (!from.HasValidData()) { Debug.LogError("Cannot copy data as some of it is invalid"); return(false); } if (to == null) { Debug.LogError("Cannot copy data to null mesh"); return(false); } if ((dataFlags & DataFlags.Vertices) != 0) { to.SetVertices(from.VertexBuffer); } if ((dataFlags & DataFlags.Normals) != 0) { to.SetNormals(from.NormalBuffer); } if ((dataFlags & DataFlags.Tangents) != 0) { to.SetTangents(from.TangentBuffer); } if ((dataFlags & DataFlags.UVs) != 0) { to.SetUVs(0, from.UVBuffer); } if ((dataFlags & DataFlags.Colors) != 0) { to.SetColors(from.ColorBuffer); } if ((dataFlags & DataFlags.Triangles) != 0) { for (int i = 0; i < to.subMeshCount; i++) { var submesh = to.GetSubMesh(i); to.SetIndices ( indices: from.IndexBuffer, indicesStart: submesh.indexStart, indicesLength: submesh.indexCount, topology: submesh.topology, submesh: i, calculateBounds: false, baseVertex: submesh.baseVertex ); } } if ((dataFlags & DataFlags.Bounds) != 0) { to.bounds = from.Bounds[0]; } return(true); }
public object GetDataFlag(string flag) { var dataFlag = DataFlags?.FirstOrDefault(e => e.Key == flag); return((DataFlags != null && dataFlag.HasValue && DataFlags.Count > 0) ? dataFlag.Value.Value ?? false : false); }
public Record(DataFlags dataflags, ulong msgNum, DateTime time, ReaderThreadInfo threadInfo, Reader.Session session, string msg) { MsgNum = msgNum; Time = time; Thread = threadInfo.Thread; ThreadName = threadInfo.ThreadName; TLevel = threadInfo.TLevel; Logger = threadInfo.Logger; StackDepth = threadInfo.Depth; MethodName = threadInfo.MethodName; Caller = threadInfo.StackTop; Session = session; if ((dataflags & DataFlags.MethodEntry) != DataFlags.None) { // This is a method entry record. It always contains exactly one line of text. IsEntry = true; Lines = new string[] { string.Format("{{{0}: entered", MethodName.Name) }; } else if ((dataflags & DataFlags.MethodExit) != DataFlags.None) { // Method exit records always contain exactly one line of text. IsExit = true; Lines = new string[] { string.Format("}}{0}: exiting", MethodName.Name) }; } else { // The message text for this record may contain newlines. Split the // message into one or more lines. Lines = msg.Split(_splitArg); if (Lines.Length > 1) { // It's common for a carriage return to exist at the // end of each line. Remove them. for (int i = 0; i < Lines.Length; ++i) { Lines[i] = Lines[i].TrimEnd('\r'); } // It's common for the last line to be empty. If so, remove it. if (Lines.Last().Trim() == string.Empty) { Lines = Lines.Take(Lines.Length - 1).ToArray(); } } IsCollapsed = Lines.Length > 1 && !Settings.Default.ExpandNewlines; } // Each line also has a bool to indicate if it is bookmarked // and a row index it may map to. IsBookmarked = new bool[Lines.Length]; RowIndices = new int[Lines.Length]; }
public DataFlags GetDataFlags() { DataFlags dataFlags = new DataFlags(); dataFlags.Offset = DataSectionLocation * 4 + 108; for (int i = 0; i < 4; i++) { dataFlags.ActionFlags.Add(PsaFile.DataSection[DataSectionLocation + 27 + i]); } Console.WriteLine(dataFlags.Offset.ToString("X")); dataFlags.ActionFlags.ForEach(x => Console.WriteLine(x.ToString("X8"))); return(dataFlags); }
/// <summary> /// Imposta valore flag /// </summary> /// <param name="index"></param> /// <param name="flag"></param> /// <param name="value"></param> internal void SetFlags(int index, DataFlags flags, bool value) { if (value) { //Imposta this.PropFlags[index] |= flags; } else { //Deimposta this.PropFlags[index] &= ~flags; } }
// This is called when reading the circular part of the log to // double check that we have a valid record. private bool FlagsAreValid(DataFlags flags) { // InvalidOnes are the bits that must always be 0 (record is // invalid if any are 1). if ((flags & DataFlags.InvalidOnes) != 0) { return(false); } // MethodEntry and MethodExit should never appear together. if ((flags & DataFlags.MethodEntry) != 0 && (flags & DataFlags.MethodExit) != 0) { return(false); } if (_reader.FormatVersion < 6) { // Circular flag should never appear in the circular part if (InCircularPart && (flags & DataFlags.CircularStart) != 0) { return(false); } if ((flags & DataFlags.NewSession) != 0) { return(false); } } else { if ((flags & DataFlags.BlockStart) != 0) { // Certain bits must always be set with BlockStart. const DataFlags mustBeSet = DataFlags.Time | DataFlags.StackDepth | DataFlags.MethodName | DataFlags.TraceLevel | DataFlags.ThreadId | DataFlags.LoggerName; if ((flags & mustBeSet) != mustBeSet) { return(false); } } // If NewSession bit is set, it must be the only one. if (((flags & DataFlags.NewSession) != 0) && (flags != DataFlags.NewSession)) { return(false); } } return(true); }
/// <summary> /// Applies the dynamic native data's vertices, normals and bounds to the dynamic mesh. /// </summary> public void ApplyData(DataFlags dataFlags) { if (DynamicMesh == null) { return; } #if UNITY_2019_3_OR_NEWER DataUtils.CopyNativeDataToMesh(DynamicNative, DynamicMesh, dataFlags); #else DataUtils.CopyNativeDataToManagedData(DynamicManaged, DynamicNative, dataFlags); DataUtils.CopyManagedDataToMesh(DynamicManaged, DynamicMesh, dataFlags); #endif }
private void SetMaxFFT(DataFlags value) { switch (value) { case DataFlags.FFT512: _maxHz = 1024; _maxFft = value; _maxFftSampleIndex = byte.MaxValue; break; case DataFlags.FFT1024: _maxHz = 1024; _maxFft = value; _maxFftSampleIndex = 511; break; case DataFlags.FFT2048: _maxHz = 2048; _maxFft = value; _maxFftSampleIndex = 1023; break; case DataFlags.FFT4096: _maxHz = 4096; _maxFft = value; _maxFftSampleIndex = 2047; break; case DataFlags.FFT8192: _maxHz = 8192; _maxFft = value; _maxFftSampleIndex = 4095; break; default: _maxHz = 4096; _maxFft = DataFlags.FFT4096; _maxFftSampleIndex = 2047; break; } if (_maxFrequencySpectrum <= _maxFftSampleIndex) { return; } _maxFrequencySpectrum = _maxFftSampleIndex; }
// This reads blocks starting at nextBlockPos and follows the chain of blocks back from there until an invalid block is // found. All parameters are assumed to be valid when called. Upon returning curFlags is set to the // last valid block found in the file. The file position is left after the flags, block number, and // record number of the last valid block. // Returns the file position of the DataFlags for the found block. // Used in file format version 6+. private long FindFirstBlock(long nextBlockPos, ref DataFlags curFlags, ref ulong curRecNum, ref uint curBlockNum) { // curFilePos is the file position of the last good block, after reading // the flags, block num, and record num. long curFilePos = _fileReader.BaseStream.Position; bool good; _fileReader.BaseStream.Position = nextBlockPos; try { do { good = false; var flags = (DataFlags)_fileReader.ReadUInt16(); if (FlagsAreValid(flags)) { var blockNum = _fileReader.ReadUInt32(); if (blockNum == curBlockNum - 1) { var recNum = _fileReader.ReadUInt64(); nextBlockPos = _fileReader.ReadInt64(); if (nextBlockPos >= _circularStartPos && nextBlockPos < _fileReader.BaseStream.Position) { curFlags = flags; curRecNum = recNum; curBlockNum = blockNum; curFilePos = _fileReader.BaseStream.Position; _fileReader.BaseStream.Position = nextBlockPos; good = true; } } } } while (good); } catch (Exception) { } _fileReader.BaseStream.Position = curFilePos; // Return the file position of the DataFlags for the found block. return(curFilePos - sizeof(DataFlags) - sizeof(UInt32) - sizeof(ulong) - sizeof(long)); }
public static bool CopyManagedDataToMesh(ManagedMeshData from, Mesh to, DataFlags dataFlags) { if (!from.HasValidData()) { Debug.LogError("Cannot copy data as some of it is invalid"); return(false); } if (to == null) { Debug.LogError("Cannot copy data to null mesh"); return(false); } // Send managed data to mesh. if ((dataFlags & DataFlags.Vertices) != 0) { to.vertices = from.Vertices; } if ((dataFlags & DataFlags.Normals) != 0) { to.normals = from.Normals; } if ((dataFlags & DataFlags.Tangents) != 0) { to.tangents = from.Tangents; } if ((dataFlags & DataFlags.UVs) != 0) { to.uv = from.UVs; } if ((dataFlags & DataFlags.Colors) != 0) { to.colors = from.Colors; } if ((dataFlags & DataFlags.Triangles) != 0) { to.triangles = from.Triangles; } if ((dataFlags & DataFlags.Bounds) != 0) { to.bounds = from.Bounds; } return(true); }
private TextReader GetAndBackupDataFromFallback(string query, DataFlags flags) { if (FallbackAccessor == null) { throw new Exception("Cannot get requested data for " + query); } if (!Directory.Exists(DataDirectory)) { Directory.CreateDirectory(DataDirectory); } using (TextReader fallbackReader = FallbackAccessor.GetDataReader(query, flags)) { string fileContent = fallbackReader.ReadToEnd(); File.WriteAllText(Path.Combine(DataDirectory, query.Replace(":", string.Empty)), fileContent, Encoding.UTF8); // Todo remove hard encoding return(new StringReader(fileContent)); } }
/// <summary> /// Gets data from filesystem or if not available from fallback (e.g. CHPP online connection) /// </summary> /// <param name="query">data query as defined at chpp API</param> /// <param name="flags">flags that give hint about data properties</param> /// <returns>TextReader to data</returns> public TextReader GetDataReader(string query, DataFlags flags) { string filepath = Path.Combine(DataDirectory, query.Replace(":", string.Empty)); // TODO use: replace all non filename chars if ((flags & DataFlags.Static) == DataFlags.Static || // if data isn't expected to change FallbackAccessor == null) // or if we don't have any fallback (e.g. online) { if (File.Exists(filepath)) { using (FileStream fileStream = File.OpenRead(filepath)) { MemoryStream memoryStream = new MemoryStream((int)fileStream.Length); fileStream.CopyTo(memoryStream); // copying file to memory allows Dispose of FileStream here // this should definitely be done my clients later, not here (TODO) memoryStream.Position = 0; return(new StreamReader(memoryStream)); } } } return(GetAndBackupDataFromFallback(query, flags)); }
/// <summary> /// Applies the dynamic native data's vertices, normals and bounds to the dynamic mesh. /// </summary> public void ApplyData(DataFlags dataFlags) { // Copy the native data into the managed data for efficient transfer into the actual mesh. DataUtils.CopyNativeDataToManagedData(dynamicManaged, DynamicNative, dataFlags); if (DynamicMesh == null) { return; } // Send managed data to mesh. if ((dataFlags & DataFlags.Vertices) != 0) { DynamicMesh.vertices = dynamicManaged.Vertices; } if ((dataFlags & DataFlags.Normals) != 0) { DynamicMesh.normals = dynamicManaged.Normals; } if ((dataFlags & DataFlags.Tangents) != 0) { DynamicMesh.tangents = dynamicManaged.Tangents; } if ((dataFlags & DataFlags.UVs) != 0) { DynamicMesh.uv = dynamicManaged.UVs; } if ((dataFlags & DataFlags.Colors) != 0) { DynamicMesh.colors = dynamicManaged.Colors; } if ((dataFlags & DataFlags.Triangles) != 0) { DynamicMesh.triangles = dynamicManaged.Triangles; } if ((dataFlags & DataFlags.Bounds) != 0) { DynamicMesh.bounds = dynamicManaged.Bounds; } }
/// <summary> /// Copies mesh data from native arrays into managed ones. /// </summary> public static bool CopyNativeDataToManagedData(ManagedMeshData managed, NativeMeshData native, DataFlags dataFlags) { var dataIsValid = true; if (!managed.HasValidData()) { dataIsValid = false; Debug.LogError("Cannot copy data as the managed data is invalid"); } if (!native.HasValidData()) { Debug.LogError("Cannot copy data as the native data is invalid"); dataIsValid = false; } if (!dataIsValid) { return(false); } if ((dataFlags & DataFlags.Vertices) != 0) { native.VertexBuffer.MemCpy(managed.Vertices); } if ((dataFlags & DataFlags.Normals) != 0) { native.NormalBuffer.MemCpy(managed.Normals); } if ((dataFlags & DataFlags.Tangents) != 0) { native.TangentBuffer.MemCpy(managed.Tangents); } if ((dataFlags & DataFlags.UVs) != 0) { native.UVBuffer.MemCpy(managed.UVs); } if ((dataFlags & DataFlags.Colors) != 0) { native.ColorBuffer.MemCpy(managed.Colors); } if ((dataFlags & DataFlags.Triangles) != 0) { native.IndexBuffer.CopyTo(managed.Triangles); } if ((dataFlags & DataFlags.Bounds) != 0) { managed.Bounds = native.Bounds[0]; } return(true); }
// This sets bits in the flags parameter that specify what data to include with the line. private DataFlags SetDataFlags(DataFlags flags, ThreadData threadData, BinaryFileState fileThreadState, Logger logger, TraceLevel lineLevel) { if (_lastBlock != _curBlock) { // The very first line in each block (regardless of thread) // includes the time in case this line ends up being the first line due to wrapping. flags |= DataFlags.Time; if (CircularStarted) { flags |= DataFlags.BlockStart; } } if (fileThreadState.LastBlock != _curBlock) { // First line in current block for the thread. Include all per-thread data. flags |= DataFlags.StackDepth | DataFlags.MethodName | DataFlags.TraceLevel | DataFlags.ThreadId | DataFlags.LoggerName; if (threadData.Name != null) { flags |= DataFlags.ThreadName; } } else { if (_lastThread != threadData) { // This line's thread differs from the last line's thread. flags |= DataFlags.ThreadId; } if (fileThreadState.LastThreadName != threadData.Name) { // Thread's name has changed. flags |= DataFlags.ThreadId | DataFlags.ThreadName; } if (fileThreadState.CurrentMethod != fileThreadState.LastMethod) { // We have a new method name for this thread. flags |= DataFlags.MethodName; } if (fileThreadState.LastTraceLevel != lineLevel) { // This line's trace Level differs from the previous line // logged by this thread. flags |= DataFlags.TraceLevel; } if (fileThreadState.LastLogger != logger) { // This line's logger name differs from the previous line // logged by this thread. flags |= DataFlags.LoggerName; } } return(flags); }
// This is what actually writes the output. The dataFlags parameter specifies what to write. private void WriteData(DataFlags dataFlags, ThreadData threadData, BinaryFileState fileThreadState, Logger logger, TraceLevel lineLevel, string msg) { ++_lineCnt; // Write the flags first so the viewer will know what else the record contains. _logfile.Write((ushort)dataFlags); if (CircularStarted) { _logfile.Write(_curBlock); if ((dataFlags & DataFlags.BlockStart) != DataFlags.None) { // This will be the first record in the block. // This stuff helps the viewer find the first chronological block // even after wrapping. Writting _lastBlockPosition forms a linked // list of blocks that the viewer can follow. //System.Diagnostics.Debug.Print("Block {0} starting at line {1}, position {2}", _curBlock, _lineCnt, _logfile.BaseStream.Position); _logfile.Write(_lineCnt); _logfile.Write(_lastBlockPosition); } } if ((dataFlags & DataFlags.Time) != DataFlags.None) { _logfile.Write(_curTime.Ticks); } if ((dataFlags & DataFlags.ThreadId) != DataFlags.None) { _logfile.Write(threadData.TracerXID); } if ((dataFlags & DataFlags.ThreadName) != DataFlags.None) { // ThreadPool thread names get reset to null when a thread is returned // to the pool and reused later. if (_hasPassword) { _encryptor.Encrypt(threadData.Name ?? string.Empty); } else { _logfile.Write(threadData.Name ?? string.Empty); } } if ((dataFlags & DataFlags.TraceLevel) != DataFlags.None) { _logfile.Write((byte)lineLevel); } // In format version 5 and later, the viewer subtracts 1 from the stack depth on // MethodExit lines instead of the logger, so just write the depth as-is. if ((dataFlags & DataFlags.StackDepth) != DataFlags.None) { _logfile.Write(fileThreadState.StackDepth); if (CircularStarted) { // In the circular part, include the thread's call stack with the first line // logged for each thread in each block. This enables the viewer to // regenerate method entry/exit lines lost due to wrapping. // Added in format version 5. int count = 0; for (StackEntry stackEntry = threadData.TopStackEntry; stackEntry != null; stackEntry = stackEntry.Caller) { if (stackEntry.BinaryFileState == fileThreadState) { ++count; _logfile.Write(stackEntry.EntryLine); // Changed to ulong in version 6. _logfile.Write((byte)stackEntry.Level); if (_hasPassword) { Debug.Assert(stackEntry.Logger.Name != null); _encryptor.Encrypt(stackEntry.Logger.Name); Debug.Assert(stackEntry.MethodName != null); _encryptor.Encrypt(stackEntry.MethodName); } else { _logfile.Write(stackEntry.Logger.Name); _logfile.Write(stackEntry.MethodName); } } } // The StackDepth we wrote previously is how the viewer will know how many // stack entries to read. System.Diagnostics.Debug.Assert(count == fileThreadState.StackDepth); } } if ((dataFlags & DataFlags.LoggerName) != DataFlags.None) { if (_hasPassword) { _encryptor.Encrypt(logger.Name); } else { _logfile.Write(logger.Name); } } if ((dataFlags & DataFlags.MethodName) != DataFlags.None) { if (_hasPassword) { _encryptor.Encrypt(fileThreadState.CurrentMethod); } else { _logfile.Write(fileThreadState.CurrentMethod); } fileThreadState.LastMethod = fileThreadState.CurrentMethod; } if ((dataFlags & DataFlags.Message) != DataFlags.None) { if (_hasPassword) { _encryptor.Encrypt(msg ?? ""); } else { _logfile.Write(msg); } } _lastBlock = _curBlock; _lastThread = threadData; fileThreadState.LastBlock = _curBlock; fileThreadState.LastThreadName = threadData.Name; fileThreadState.LastTraceLevel = lineLevel; fileThreadState.LastLogger = logger; }
// Called immediately after writing a line of output in circular mode. // This may wrap and/or truncate the file, but does not write any output. // This does update the file's LastWriteTime. // startPos = the file position of the beginning of the line just written. private void ManageCircularPart(long startPos, long startSize, DataFlags dataFlags) { long endPos = _logfile.BaseStream.Position; // Truncate the file if we just overwrote the block that extends past max file size, since // the viewer can't access that info, it can be arbitrarily large, and it screws things up // if another logging session appends output to the file. if (_maxBlockPosition >= startPos && _maxBlockPosition < endPos) { //System.Diagnostics.Debug.Print("Last physical block start was overwritten at " + _maxBlockPosition + ". Truncating file at " + endPos); _maxBlockPosition = 0; _logfile.BaseStream.SetLength(endPos); } if (endPos >= _maxFilePosition) { // Since we've reached or exceeded the max file size/position, it's time to wrap and // start a new block even if the current block only has one line. //System.Diagnostics.Debug.Print("File position exceeded max size."); // Remember the file location of this block because it extends // past the max file size. _maxBlockPosition = _curBlockPosition; // Wrap back to the beginning of the circular part. _logfile.BaseStream.Position = _positionOfCircularPart; // Cause the current block to end and a new block to start. EndCurrentBlock(); if (!_everWrapped) { Logger.EventLogging.Log("The output file wrapped for the first time: " + FullPath, Logger.EventLogging.FirstWrap); _everWrapped = true; } } else { // Keep track of how many bytes are in this block so we can determine // if it's time to start a new one based on block size. _bytesInBlock += (uint)(endPos - startPos); // Now check if the current block has enough bytes to start a new block. if (_bytesInBlock >= _blockSize) { EndCurrentBlock(); } } if (_everWrapped) { // On XP, the file's LastWriteTime changes automatically when the logger writes to the // file ONLY IF the size changes too. If the file has wrapped (meaning the size rarely changes), // we "manually" update the LastWriteTime. Thus, on XP, both properties change until // the file wraps, and then only the LastWriteTime changes. // On Vista, the LastWriteTime doesn't change automatically until the logger closes the // file (even if the size does change). However, the size will change until the file wraps, // then we start "manually" setting the LastWriteTime. Thus, on Vista, only the size changes // until the file wraps, then only the LastWriteTime changes. The viewer monitors both properties. if (_logfile.BaseStream.Length == startSize && (dataFlags & DataFlags.Time) != DataFlags.None) { // The line we just wrote did not change the file size so manually update the file's LastWiteTime. long writeTime = _curTime.ToLocalTime().ToFileTime(); SetFileTime(_fileHandle, IntPtr.Zero, IntPtr.Zero, ref writeTime); } } }
// Determine what data needs to be written based on dataFlags, // whether circular logging has or should be started, // and whether we're starting a new circular block. // Write the output to the file. Manage the circular part of the log. // Return the line number just written. private ulong WriteLine(DataFlags dataFlags, ThreadData threadData, Logger logger, TraceLevel lineLevel, DateTime explicitUtcTime, string msg, bool recursive) { BinaryFileState fileThreadState = threadData.GetBinaryFileState(this); lock (_fileLocker) { try { if (IsOpen) { if (fileThreadState.LastFileNumber != CurrentFile) { // First time writing to this file. threadData.ResetBinaryFileStateData(CurrentFile, dataFlags); } // Calling IsNewTime() can change _curTime. if (IsNewTime(explicitUtcTime) || recursive) { // Time differs from previous line. // Set the flag indicating it will be written dataFlags |= DataFlags.Time; } // Possibly start the circular log based on _curTime and/or file size. // Put this after calling IsNewTime() so _curTime will have // the latest DateTime value. if (FullFilePolicy == FullFilePolicy.Wrap && !recursive && !CircularStarted && (_curTime >= _circularStartTime || (CircularStartSizeKb > 0 && (_logfile.BaseStream.Position - _openSize) >= CircularStartSizeKb << 10))) { // This will start the circular part of the log if there is enough // room based on current file position and max file size. // It will increment _curBlock if it starts the circular log. // It will also make a recursive call to this method via Metalog. StartCircular(logger, lineLevel); } // Set bits in Flags that indicate what data should be written for this line. dataFlags = SetDataFlags(dataFlags, threadData, fileThreadState, logger, lineLevel); // We need to know the start position of the line we're about // to write to determine if it overwrites the beginning of the oldest block. long startPos = _logfile.BaseStream.Position; // We capture the size of the file before writing the message so we can tell // if the size changes. long startSize = _logfile.BaseStream.Length; // Write the Flags to the file followed by the data the Flags say to log. WriteData(dataFlags, threadData, fileThreadState, logger, lineLevel, msg); // If the file is being viewed, this will notify the viewer that the file was changed. _viewerSignaler.SignalEvents(); if (CircularStarted) { ManageCircularPart(startPos, startSize, dataFlags); } else if (_logfile.BaseStream.Position >= _maxFilePosition) { // We can't do any meta-logging here because the viewer expects the first record to reach // _maxFilePosition (which we just wrote) to be the last. Writing another record would cause errors. switch (FullFilePolicy) { case FullFilePolicy.Close: Close(); break; case FullFilePolicy.Roll: // If logging a method-entry or method-exit, wait until the next call // to close and open. if ((dataFlags & (DataFlags.MethodEntry | DataFlags.MethodExit)) == 0) { // These calls may raise events whose handlers modify our properties. Close(); Open(); } break; case FullFilePolicy.Wrap: // Reaching max file size/position without being in circular mode means we'll never write to // this file again, so we might as well close it. Since this is probably not what the user intended, // also log an event. string errmsg = "The maximum file size of " + _maxFilePosition + " was reached before circular logging was engaged. The log file is " + FullPath; Logger.EventLogging.Log(errmsg, Logger.EventLogging.MaxFileSizeReached); Close(); break; } } } } catch (Exception ex) { // Give up! close the log file, free whatever memory we can. Logger.EventLogging.Log("An exception was thrown while logging: " + ex.ToString(), Logger.EventLogging.ExceptionInLogger); Close(); } return(_lineCnt); } }
public static bool CopyToManagedData(this NativeMeshData from, ManagedMeshData to, DataFlags dataFlags) => CopyNativeDataToManagedData(to, from, dataFlags);
/// <summary> /// Copies the original native data over the dynamic native data. /// </summary> public void ResetData(DataFlags dataFlags) { // Copy the original mesh data into the native data to remove any changes. DataUtils.CopyNativeDataToNativeData(OriginalNative, DynamicNative, dataFlags); }
/// <summary> /// Copies mesh data from one native array to another /// </summary> public static bool CopyNativeDataToNativeData(NativeMeshData from, NativeMeshData to, DataFlags dataFlags) { if (!to.HasValidData() || !from.HasValidData()) { Debug.LogError("Cannot copy data as some of it is invalid"); return(false); } if ((dataFlags & DataFlags.Vertices) != 0) { from.VertexBuffer.CopyTo(to.VertexBuffer); } if ((dataFlags & DataFlags.Normals) != 0) { from.NormalBuffer.CopyTo(to.NormalBuffer); } if ((dataFlags & DataFlags.MaskVertices) != 0) { from.MaskVertexBuffer.CopyTo(to.MaskVertexBuffer); } if ((dataFlags & DataFlags.Tangents) != 0) { from.TangentBuffer.CopyTo(to.TangentBuffer); } if ((dataFlags & DataFlags.UVs) != 0) { from.UVBuffer.CopyTo(to.UVBuffer); } if ((dataFlags & DataFlags.Colors) != 0) { from.ColorBuffer.CopyTo(to.ColorBuffer); } if ((dataFlags & DataFlags.Triangles) != 0) { from.IndexBuffer.CopyTo(to.IndexBuffer); } if ((dataFlags & DataFlags.Bounds) != 0) { from.Bounds.CopyTo(to.Bounds); } return(true); }
public static bool CopyToMesh(this NativeMeshData from, Mesh to, DataFlags dataFlags) => CopyNativeDataToMesh(from, to, dataFlags);
public static bool CopyToNativeData(this ManagedMeshData from, NativeMeshData to, DataFlags dataFlags) => CopyManagedToNativeMeshData(from, to, dataFlags);
public static bool CopyToMesh(ManagedMeshData from, Mesh to, DataFlags dataFlags) => CopyManagedDataToMesh(from, to, dataFlags);
/// <summary> /// Copies mesh data from managed arrays into native ones. /// </summary> /// <param name="onlyEssentials">If true, only vertices, normals, bounds, and mask vertices will be copied.</param> public static void CopyManagedToNativeMeshData(ManagedMeshData managed, NativeMeshData native, DataFlags dataFlags) { var dataIsValid = true; if (!managed.HasValidData()) { dataIsValid = false; Debug.LogError("Cannot copy data as the managed data is invalid"); } if (!native.HasValidData()) { Debug.LogError("Cannot copy data as the native data is invalid"); dataIsValid = false; } if (!dataIsValid) { return; } if ((dataFlags & DataFlags.Vertices) != 0) { managed.Vertices.MemCpy(native.VertexBuffer); } if ((dataFlags & DataFlags.Normals) != 0) { managed.Normals.MemCpy(native.NormalBuffer); } if ((dataFlags & DataFlags.MaskVertices) != 0) { managed.Vertices.MemCpy(native.MaskVertexBuffer); } if ((dataFlags & DataFlags.Tangents) != 0) { managed.Tangents.MemCpy(native.TangentBuffer); } if ((dataFlags & DataFlags.UVs) != 0) { managed.UVs.MemCpy(native.UVBuffer); } if ((dataFlags & DataFlags.Colors) != 0) { managed.Colors.MemCpy(native.ColorBuffer); } if ((dataFlags & DataFlags.Triangles) != 0) { managed.Triangles.MemCpy(native.IndexBuffer); } if ((dataFlags & DataFlags.Bounds) != 0) { native.Bounds[0] = managed.Bounds; } }