diff --git a/src/AddIns/Misc/Profiler/Controller/Controller.csproj b/src/AddIns/Misc/Profiler/Controller/Controller.csproj
index 89b73bd3ab..c83c0abb80 100644
--- a/src/AddIns/Misc/Profiler/Controller/Controller.csproj
+++ b/src/AddIns/Misc/Profiler/Controller/Controller.csproj
@@ -66,6 +66,7 @@
+
diff --git a/src/AddIns/Misc/Profiler/Controller/Data/IncompatibleDatabaseException.cs b/src/AddIns/Misc/Profiler/Controller/Data/IncompatibleDatabaseException.cs
new file mode 100644
index 0000000000..e02400b3bc
--- /dev/null
+++ b/src/AddIns/Misc/Profiler/Controller/Data/IncompatibleDatabaseException.cs
@@ -0,0 +1,66 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Runtime.Serialization;
+
+namespace ICSharpCode.Profiler.Controller.Data
+{
+ ///
+ /// Thrown when the database used to internally store the usage data is incompatible with the DB version
+ /// expected by the UsageDataCollector library.
+ ///
+ [Serializable]
+ public class IncompatibleDatabaseException : Exception
+ {
+ ///
+ /// Expected database version.
+ ///
+ public Version ExpectedVersion { get; set; }
+
+ ///
+ /// Actual database version.
+ ///
+ public Version ActualVersion { get; set; }
+
+ ///
+ /// Creates a new IncompatibleDatabaseException instance.
+ ///
+ public IncompatibleDatabaseException() {}
+
+ ///
+ /// Creates a new IncompatibleDatabaseException instance.
+ ///
+ public IncompatibleDatabaseException(Version expectedVersion, Version actualVersion)
+ : base("Expected DB version " + expectedVersion + " but found " + actualVersion)
+ {
+ this.ExpectedVersion = expectedVersion;
+ this.ActualVersion = actualVersion;
+ }
+
+ ///
+ /// Deserializes an IncompatibleDatabaseException instance.
+ ///
+ protected IncompatibleDatabaseException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ if (info != null) {
+ this.ExpectedVersion = (Version)info.GetValue("ExpectedVersion", typeof(Version));
+ this.ActualVersion = (Version)info.GetValue("ActualVersion", typeof(Version));
+ }
+ }
+
+ ///
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ if (info != null) {
+ info.AddValue("ExpectedVersion", this.ExpectedVersion, typeof(Version));
+ info.AddValue("ActualVersion", this.ActualVersion, typeof(Version));
+ }
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs b/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs
index a5afa7fb36..bf84f348a8 100644
--- a/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs
+++ b/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs
@@ -42,6 +42,16 @@ namespace ICSharpCode.Profiler.Controller.Data
this.connection = new SQLiteConnection(conn.ConnectionString);
this.connection.Open();
+
+ CheckFileVersion();
+ }
+
+ void CheckFileVersion()
+ {
+ string version = GetProperty("version");
+
+ if (version != "1.0")
+ throw new IncompatibleDatabaseException(new Version(1, 0), new Version(version));
}
///
@@ -69,42 +79,11 @@ namespace ICSharpCode.Profiler.Controller.Data
internal IQueryable GetCallers(SQLiteCallTreeNode item)
{
- SQLiteCommand cmd;
- using (LockAndCreateCommand(out cmd)) {
- cmd.CommandText = @"SELECT id, nameid, callcount, timespent, isactiveatstart
- FROM FunctionData
- WHERE id IN(
- SELECT parentid
- FROM FunctionData
- WHERE id IN(" + string.Join(",", item.ids.Select(s => s.ToString()).ToArray()) + @")
- )
- ORDER BY id;";
-
- Debug.Print("GetCallers cmd: " + cmd.CommandText);
-
- using (SQLiteDataReader reader = cmd.ExecuteReader()) {
- List items = new List();
-
- while (reader.Read()) {
- int childNameId = reader.GetInt32(1);
- SQLiteCallTreeNode newItem = items.Find(node => node.nameId == childNameId);
- if (newItem == null) {
- newItem = new SQLiteCallTreeNode(childNameId, null, this);
- newItem.selectionStartIndex = item.selectionStartIndex;
- items.Add(newItem);
-
- // works because of ORDER BY id
- newItem.isActiveAtStart = reader.GetBoolean(4);
- }
-
- newItem.callCount += reader.GetInt32(2);
- newItem.cpuCyclesSpent += (ulong)reader.GetInt64(3);
- newItem.ids.Add(reader.GetInt32(0));
- }
-
- return items.Cast().AsQueryable(); // TODO : remove Cast<> in .NET 4.0
- }
- }
+ return GetMergedFunctionData(@"id IN(
+ SELECT parentid
+ FROM FunctionData
+ WHERE id IN(" + string.Join(",", item.ids.Select(s => s.ToString()).ToArray()) + ")" +
+ ")", item.selectionStartIndex);
}
///
diff --git a/src/AddIns/Misc/Profiler/Controller/Data/SQLiteCallTreeNode.cs b/src/AddIns/Misc/Profiler/Controller/Data/SQLiteCallTreeNode.cs
index c9b390b8e3..a0e45d0d2d 100644
--- a/src/AddIns/Misc/Profiler/Controller/Data/SQLiteCallTreeNode.cs
+++ b/src/AddIns/Misc/Profiler/Controller/Data/SQLiteCallTreeNode.cs
@@ -20,7 +20,6 @@ namespace ICSharpCode.Profiler.Controller.Data
class SQLiteCallTreeNode : CallTreeNode
{
internal int nameId;
- internal bool isActiveAtStart;
internal int callCount;
internal ulong cpuCyclesSpent;
CallTreeNode parent;
@@ -106,12 +105,12 @@ namespace ICSharpCode.Profiler.Controller.Data
///
public override bool IsActiveAtStart {
get {
- return isActiveAtStart;
+ return activeCallCount > 0;
}
}
public override int CallCount {
- get { return callCount + activeCallCount; }
+ get { return Math.Max(1, callCount + activeCallCount); }
}
///
@@ -122,13 +121,17 @@ namespace ICSharpCode.Profiler.Controller.Data
public override CallTreeNode Merge(IEnumerable nodes)
{
SQLiteCallTreeNode mergedNode = new SQLiteCallTreeNode(0, null, this.provider);
+ mergedNode.selectionStartIndex = int.MaxValue;
bool initialised = false;
foreach (SQLiteCallTreeNode node in nodes) {
mergedNode.ids.AddRange(node.ids);
+ mergedNode.hasChildren |= node.hasChildren;
mergedNode.selectionStartIndex = Math.Min(mergedNode.selectionStartIndex, node.selectionStartIndex);
mergedNode.callCount += node.callCount;
+ mergedNode.activeCallCount += node.activeCallCount;
mergedNode.cpuCyclesSpent += node.cpuCyclesSpent;
+
if (!initialised || mergedNode.nameId == node.nameId)
mergedNode.nameId = node.nameId;
else
diff --git a/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/CopySelectedData.cs b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/CopySelectedData.cs
index 6209ca52a8..a2fb39f5a2 100644
--- a/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/CopySelectedData.cs
+++ b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/CopySelectedData.cs
@@ -35,7 +35,16 @@ namespace ICSharpCode.Profiler.AddIn.Commands
foreach (CallTreeNodeViewModel node in list) {
if (node != null)
- builder.AppendLine(new string('\t', node.Level) + node.Name + "\t" + node.CallCount + "\t" + node.TimeSpent + "\t" + node.TimePercentageOfParentAsText);
+ builder.AppendLine(
+ new string('\t', node.Level) +
+ node.Name + "\t" +
+ node.CallCount + "\t" +
+ node.TimeSpent + "\t" +
+ node.TimeSpentSelf + "\t" +
+ node.TimeSpentPerCall + "\t" +
+ node.TimeSpentSelfPerCall + "\t" +
+ node.TimePercentageOfParentAsText
+ );
}
Clipboard.SetText(builder.ToString());
diff --git a/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Views/ProfilerDisplayBinding.cs b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Views/ProfilerDisplayBinding.cs
index 2ae212d2c6..a35d723dfa 100644
--- a/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Views/ProfilerDisplayBinding.cs
+++ b/src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Views/ProfilerDisplayBinding.cs
@@ -5,10 +5,11 @@
// $Revision$
//
-using ICSharpCode.Profiler.Controller.Data;
+using ICSharpCode.Core;
using System;
using System.IO;
using ICSharpCode.Profiler.Controller;
+using ICSharpCode.Profiler.Controller.Data;
using ICSharpCode.SharpDevelop;
namespace ICSharpCode.Profiler.AddIn.Views
@@ -29,7 +30,12 @@ namespace ICSharpCode.Profiler.AddIn.Views
public ICSharpCode.SharpDevelop.Gui.IViewContent CreateContentForFile(OpenedFile file)
{
- return new WpfViewer(file);
+ try {
+ return new WpfViewer(file);
+ } catch (IncompatibleDatabaseException e) {
+ MessageService.ShowErrorFormatted("${res:AddIns.Profiler.DatabaseTooNewError}", e.ActualVersion.ToString(), e.ExpectedVersion.ToString());
+ return null;
+ }
}
}
}