diff --git a/ide_plugins/vs/coati_plugin_vs.vsix b/ide_plugins/vs/coati_plugin_vs.vsix index c65a1c3a..71ef196a 100644 Binary files a/ide_plugins/vs/coati_plugin_vs.vsix and b/ide_plugins/vs/coati_plugin_vs.vsix differ diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPlugin.csproj b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPlugin.csproj index cc996f65..f7dd7241 100644 --- a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPlugin.csproj +++ b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPlugin.csproj @@ -162,6 +162,7 @@ + diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPluginPackage.cs b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPluginPackage.cs index 10d786d5..384507e1 100644 --- a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPluginPackage.cs +++ b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/CoatiPluginPackage.cs @@ -366,35 +366,11 @@ namespace CoatiSoftware.CoatiPlugin _cdbList.AppendOrUpdate(creationResult._cdb); _cdbList.SaveMetaData(); - // string metaData = creationResult._cdb.SerializeMetaDataXML(); + Wizard.WindowCDBReady dialog = new Wizard.WindowCDBReady(); + dialog.setData(creationResult); + dialog.ShowDialog(); - - // Utility.DataUtility.GetInstance().AppendData(metaData); - - if (WriteCDBToFile(creationResult._cdb, creationResult._cdbDirectory, creationResult._cdbName)) - { - Wizard.WindowCDBReady dialog = new Wizard.WindowCDBReady(); - dialog.setData(creationResult); - dialog.ShowDialog(); - - _cdbList.Refresh(); - } - else - { - string title = "Error"; - string text = "Failed to write CDB '" + creationResult._cdbName + "' to directory \"" + creationResult._cdbDirectory + "\"\n"; - - if (LoggingEnabled) - { - text += "See log for details."; - } - else - { - text += "Consider enabling logging to provide additional information (Tools->Options->Coati)."; - } - - DialogResult result = MessageBox.Show(text, title, MessageBoxButtons.OK, MessageBoxIcon.Warning); - } + _cdbList.Refresh(); } else { @@ -402,39 +378,6 @@ namespace CoatiSoftware.CoatiPlugin } } - private bool WriteCDBToFile(SolutionParser.CompilationDatabase cdb, string directory, string fileName) - { - try - { - Logging.Logging.LogInfo("Serializing " + cdb.CommandObjectCount + " command objects."); - - System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); - watch.Start(); - string content = cdb.SerializeJSON(); - watch.Stop(); - Logging.Logging.LogInfo("Done serializing: " + watch.ElapsedMilliseconds + " ms"); - - File.WriteAllText(directory + "\\" + fileName + ".json", content); - } - catch(Exception e) - { - string text = "Failed to write CDB '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(fileName) + "' to directory \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(directory) + "\"\n"; - Logging.Logging.LogError(text); - Logging.Logging.LogError("Exception: " + e.Message); - - _cdbList.UnloadCDBs(); - - return false; - } - - string message = "The CDB '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(fileName) + "' was created at directory \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(directory) + "\"\n"; - Logging.Logging.LogInfo(message); - - _cdbList.UnloadCDBs(); - - return true; - } - private void MenuItemCallback(object sender, EventArgs e) { MenuCommand menuCommand = sender as MenuCommand; diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/SolutionParser/CompilationDatabase.cs b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/SolutionParser/CompilationDatabase.cs index c247e70f..af73e9a6 100644 --- a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/SolutionParser/CompilationDatabase.cs +++ b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/SolutionParser/CompilationDatabase.cs @@ -2,6 +2,9 @@ using System.Xml.Serialization; using System.Xml; using Newtonsoft.Json.Linq; +using System.IO; +using System.Threading; +using System; namespace CoatiSoftware.CoatiPlugin.SolutionParser { @@ -67,14 +70,9 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser get { return _commandObjects.Count; } } - public void AddOrUpdateCommandObject(CommandObject commandObject) + public void AddOrUpdateCommandObject(CommandObject commandObject, bool saveImmediatly = false) { _commandObjects.Add(commandObject); // updating is not efficient as it is - - //if (TryUpdateCommandObject(commandObject) == false) - //{ - // _commandObjects.Add(commandObject); - //} } // remove commandObjects for removed files diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/QueuedFileWriter.cs b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/QueuedFileWriter.cs new file mode 100644 index 00000000..7d989968 --- /dev/null +++ b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Utility/QueuedFileWriter.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; + +namespace CoatiSoftware.CoatiPlugin.Utility +{ + class QueuedFileWriter + { + private bool _working = false; + Thread _workerThread = null; + + private static ReaderWriterLockSlim _statusLock = new ReaderWriterLockSlim(); + private static ReaderWriterLockSlim _queueLock = new ReaderWriterLockSlim(); + private static ReaderWriterLockSlim _fileLock = new ReaderWriterLockSlim(); + + private Queue _inputQueue = new Queue(); + private Queue _outputQueue = new Queue(); + + private string _targetDirectory = ""; + private string _fileName = ""; + + private int _messagesReceived = 0; + private int _messageWrittenCount = 0; + + public string TargetDirectory + { + get { return _targetDirectory; } + set { _targetDirectory = value; } + } + + public string FileName + { + get { return _fileName; } + set { _fileName = value; } + } + + public void pushMessage(string message) + { + _queueLock.EnterWriteLock(); + _messagesReceived++; + try + { + _inputQueue.Enqueue(message); + } + catch(Exception e) + { + Logging.Logging.LogError(e.Message); + } + finally + { + _queueLock.ExitWriteLock(); + } + } + + public void startWorking() + { + _statusLock.EnterReadLock(); + if (_working == true) + { + return; + } + _statusLock.ExitReadLock(); + + + _statusLock.EnterWriteLock(); + _working = true; + _workerThread = new Thread(new ThreadStart(work)); + _workerThread.Start(); + _statusLock.ExitWriteLock(); + } + + public void stopWorking() + { + _statusLock.EnterWriteLock(); + _working = false; + _statusLock.ExitWriteLock(); + + if(_workerThread != null) + { + _workerThread.Join(); + } + + // write remaining messages if stop was called + _queueLock.EnterWriteLock(); + try + { + writeQueueToFile(ref _inputQueue); + writeQueueToFile(ref _outputQueue); + + Logging.Logging.LogInfo("final commit done"); + } + catch(Exception e) + { + Logging.Logging.LogError(e.Message); + } + finally + { + _queueLock.ExitWriteLock(); + } + + Logging.Logging.LogInfo("Messages received: " + _messagesReceived); + Logging.Logging.LogInfo("Messages written: " + _messageWrittenCount); + } + + private void work() + { + bool working = true; + + while(working) + { + commit(); + + _statusLock.EnterReadLock(); + working = _working; + _statusLock.ExitReadLock(); + } + } + + private void commit() + { + _queueLock.EnterWriteLock(); + + Queue tmpQueue = _inputQueue; + _inputQueue = _outputQueue; + _outputQueue = tmpQueue; + + _queueLock.ExitWriteLock(); + + + writeQueueToFile(ref _outputQueue); + } + + private void writeQueueToFile(ref Queue messageQueue) + { + _fileLock.EnterWriteLock(); + try + { + while(messageQueue.Count > 0) + { + _messageWrittenCount++; + + string message = messageQueue.Dequeue(); + + File.AppendAllText(_targetDirectory + "\\" + _fileName, message); + } + } + catch (Exception e) + { + Logging.Logging.LogError(e.Message); + } + finally + { + _fileLock.ExitWriteLock(); + } + } + } +} diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Wizard/WindowCreateCDB.cs b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Wizard/WindowCreateCDB.cs index 26477174..19e6fde5 100644 --- a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Wizard/WindowCreateCDB.cs +++ b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/Wizard/WindowCreateCDB.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.IO; using System.Threading.Tasks; +using System.Threading; using System.Windows.Forms; namespace CoatiSoftware.CoatiPlugin.Wizard @@ -35,6 +37,9 @@ namespace CoatiSoftware.CoatiPlugin.Wizard private int _threadCount = 1; + private static object _lockObject = new object(); + private static ReaderWriterLockSlim _readWriteLock = new ReaderWriterLockSlim(); + public OnFinishedCreatingCDB CallbackOnFinishedCreatingCDB { get { return _onFinishedCreateCDB; } @@ -176,6 +181,21 @@ namespace CoatiSoftware.CoatiPlugin.Wizard private SolutionParser.CompilationDatabase CreateCommandObjects() { SolutionParser.CompilationDatabase cdb = new SolutionParser.CompilationDatabase(); + cdb.Directory = _targetDir; + cdb.Name = _fileName; + + File.WriteAllText(_targetDir + "\\" + _fileName + ".json", ""); + File.AppendAllText(_targetDir + "\\" + _fileName + ".json", "[\n"); + + // Mutex commandObjectMutex = new Mutex(); + + object lockObject = new object(); + object lockObject2 = new object(); + + Utility.QueuedFileWriter fileWriter = new Utility.QueuedFileWriter(); + fileWriter.FileName = _fileName + ".json"; + fileWriter.TargetDirectory = _targetDir; + fileWriter.startWorking(); try { @@ -185,8 +205,6 @@ namespace CoatiSoftware.CoatiPlugin.Wizard List tasks = new List(); - Object lockObject = new Object(); - int projectsProcessed = 0; foreach (EnvDTE.Project project in _projects) { @@ -198,34 +216,45 @@ namespace CoatiSoftware.CoatiPlugin.Wizard { List commandObjects = SolutionParser.SolutionParser.CreateCommandObjects(project, _configurationName, _platformName, _cStandard); - lock(lockObject) + lock (_lockObject) { projectsProcessed++; } - + float relativProgress = (float)projectsProcessed / (float)_projects.Count; Logging.Logging.LogInfo("Processing project \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(project.Name) + "\""); backgroundWorker1.ReportProgress((int)(relativProgress * 100), "Processing project \"" + project.Name + "\""); foreach (SolutionParser.CommandObject obj in commandObjects) { - cdb.AddOrUpdateCommandObject(obj); + // cdb.AddOrUpdateCommandObject(obj, false); // since the data is written to file right away now, no need to store it + // the cdb is however still needed to store some meta data later + + fileWriter.pushMessage(obj.SerializeJSON() + ","); } }); tasks.Add(t); } + + int threadCount = System.Diagnostics.Process.GetCurrentProcess().Threads.Count; Task.WaitAll(tasks.ToArray()); + fileWriter.stopWorking(); + backgroundWorker1.ReportProgress(100, "Writing data to file. This might take several minutes..."); } catch(Exception e) { Logging.Logging.LogError("Failed to create CDB: " + e.Message); } + finally + { + File.AppendAllText(_targetDir + "\\" + _fileName + ".json", "\n]"); + } return cdb; } diff --git a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/source.extension.vsixmanifest b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/source.extension.vsixmanifest index c55f153d..52f86ee0 100644 --- a/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/source.extension.vsixmanifest +++ b/ide_plugins/vs/vs2015/CoatiPlugin/CoatiPlugin/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + CoatiPlugin This package allows Coati to communicate with Visual Studio and vice versa. http://www.coati.io/