diff --git a/src/AddIns/Misc/UsageDataCollector/UsageDataSessionWriter.cs b/src/AddIns/Misc/UsageDataCollector/UsageDataSessionWriter.cs index 1a9fd45d94..e0d56b4746 100644 --- a/src/AddIns/Misc/UsageDataCollector/UsageDataSessionWriter.cs +++ b/src/AddIns/Misc/UsageDataCollector/UsageDataSessionWriter.cs @@ -108,11 +108,8 @@ namespace ICSharpCode.UsageDataCollector { using (SQLiteTransaction transaction = this.connection.BeginTransaction()) { using (SQLiteCommand cmd = this.connection.CreateCommand()) { - cmd.CommandText = "INSERT INTO Sessions (startTime) VALUES (datetime());"; - cmd.ExecuteNonQuery(); - } - using (SQLiteCommand cmd = this.connection.CreateCommand()) { - cmd.CommandText = "SELECT last_insert_rowid();"; + cmd.CommandText = "INSERT INTO Sessions (startTime) VALUES (datetime('now'));" + + "SELECT last_insert_rowid();"; sessionID = (long)cmd.ExecuteScalar(); } AddEnvironmentData("platform", Environment.OSVersion.Platform.ToString()); @@ -126,7 +123,7 @@ namespace ICSharpCode.UsageDataCollector void EndSession() { using (SQLiteCommand cmd = this.connection.CreateCommand()) { - cmd.CommandText = "UPDATE Sessions SET endTime = datetime() WHERE id = ?;"; + cmd.CommandText = "UPDATE Sessions SET endTime = datetime('now') WHERE id = ?;"; cmd.Parameters.Add(new SQLiteParameter { Value = sessionID }); cmd.ExecuteNonQuery(); } @@ -150,14 +147,12 @@ namespace ICSharpCode.UsageDataCollector using (SQLiteTransaction transaction = this.connection.BeginTransaction()) { using (SQLiteCommand cmd = this.connection.CreateCommand()) { cmd.CommandText = "INSERT INTO FeatureUses (session, time, feature, activationMethod)" + - " VALUES (?, datetime(), ?, ?);"; + " VALUES (?, datetime('now'), ?, ?);" + + "SELECT last_insert_rowid();"; cmd.Parameters.Add(new SQLiteParameter { Value = sessionID }); cmd.Parameters.Add(new SQLiteParameter { Value = featureName }); cmd.Parameters.Add(new SQLiteParameter { Value = activationMethod }); - cmd.ExecuteNonQuery(); - } - using (SQLiteCommand cmd = this.connection.CreateCommand()) { - cmd.CommandText = "SELECT last_insert_rowid();"; + featureRowId = (long)cmd.ExecuteScalar(); } transaction.Commit(); @@ -168,7 +163,7 @@ namespace ICSharpCode.UsageDataCollector public void WriteEndTimeForFeature(long featureID) { using (SQLiteCommand cmd = this.connection.CreateCommand()) { - cmd.CommandText = "UPDATE FeatureUses SET endTime = datetime() WHERE id = ?;"; + cmd.CommandText = "UPDATE FeatureUses SET endTime = datetime('now') WHERE id = ?;"; cmd.Parameters.Add(new SQLiteParameter { Value = featureID }); cmd.ExecuteNonQuery(); } @@ -178,7 +173,7 @@ namespace ICSharpCode.UsageDataCollector { using (SQLiteCommand cmd = this.connection.CreateCommand()) { cmd.CommandText = "INSERT INTO Exceptions (session, time, type, stackTrace)" + - " VALUES (?, datetime(), ?, ?);"; + " VALUES (?, datetime('now'), ?, ?);"; cmd.Parameters.Add(new SQLiteParameter { Value = sessionID }); cmd.Parameters.Add(new SQLiteParameter { Value = exceptionType }); cmd.Parameters.Add(new SQLiteParameter { Value = stacktrace }); diff --git a/src/AddIns/Misc/UsageDataCollector/UsageDataUploader.cs b/src/AddIns/Misc/UsageDataCollector/UsageDataUploader.cs index 233c47bad6..813c344187 100644 --- a/src/AddIns/Misc/UsageDataCollector/UsageDataUploader.cs +++ b/src/AddIns/Misc/UsageDataCollector/UsageDataUploader.cs @@ -38,32 +38,15 @@ namespace ICSharpCode.UsageDataCollector return connection; } - /// - /// Starts the upload of the usage data. - /// - public void StartUpload() - { - UsageDataMessage message = GetDataToBeTransmitted(false); - DataContractSerializer serializer = new DataContractSerializer(typeof(UsageDataMessage)); - using (FileStream fs = new FileStream(Path.Combine(Path.GetTempPath(), "SharpDevelopUsageData.xml.gz"), FileMode.Create, FileAccess.Write)) { - using (GZipStream zip = new GZipStream(fs, CompressionMode.Compress)) { - serializer.WriteObject(zip, message); - } - } - } - - internal UsageDataMessage GetDataToBeTransmitted(bool fetchIncompleteSessions) + public string GetTextForStoredData() { + UsageDataMessage message; using (SQLiteConnection connection = OpenConnection()) { using (SQLiteTransaction transaction = connection.BeginTransaction()) { - return FetchDataForUpload(connection, fetchIncompleteSessions); + CheckDatabaseVersion(connection); + message = FetchDataForUpload(connection, true); } } - } - - public string GetTextForStoredData() - { - UsageDataMessage message = GetDataToBeTransmitted(true); using (StringWriter w = new StringWriter()) { using (XmlTextWriter xmlWriter = new XmlTextWriter(w)) { xmlWriter.Formatting = Formatting.Indented; @@ -74,12 +57,37 @@ namespace ICSharpCode.UsageDataCollector } } - #region FetchDataForUpload + /// + /// Starts the upload of the usage data. + /// + public void StartUpload() + { + UsageDataMessage message; + using (SQLiteConnection connection = OpenConnection()) { + using (SQLiteTransaction transaction = connection.BeginTransaction()) { + CheckDatabaseVersion(connection); + if (HasAlreadyUploadedToday(connection)) { + message = null; + } else { + message = FetchDataForUpload(connection, false); + } + transaction.Commit(); + } + } + if (message != null) { + DataContractSerializer serializer = new DataContractSerializer(typeof(UsageDataMessage)); + using (FileStream fs = new FileStream(Path.Combine(Path.GetTempPath(), "SharpDevelopUsageData.xml.gz"), FileMode.Create, FileAccess.Write)) { + using (GZipStream zip = new GZipStream(fs, CompressionMode.Compress)) { + serializer.WriteObject(zip, message); + } + } + } + } + Version expectedDBVersion = new Version(1, 0, 1); - UsageDataMessage FetchDataForUpload(SQLiteConnection connection, bool fetchIncompleteSessions) + void CheckDatabaseVersion(SQLiteConnection connection) { - // Check the database version using (SQLiteCommand cmd = connection.CreateCommand()) { cmd.CommandText = "SELECT value FROM Properties WHERE name = 'dbVersion';"; string version = (string)cmd.ExecuteScalar(); @@ -90,7 +98,22 @@ namespace ICSharpCode.UsageDataCollector throw new IncompatibleDatabaseException(expectedDBVersion, actualDBVersion); } } - + } + + bool HasAlreadyUploadedToday(SQLiteConnection connection) + { + using (SQLiteCommand cmd = connection.CreateCommand()) { + cmd.CommandText = "SELECT value > datetime('now','-1 day') FROM Properties WHERE name='lastUpload';"; + object result = cmd.ExecuteScalar(); + if (result == null) + return false; // no lastUpload entry -> DB was never uploaded + return (long)result > 0; + } + } + + #region FetchDataForUpload + UsageDataMessage FetchDataForUpload(SQLiteConnection connection, bool fetchIncompleteSessions) + { UsageDataMessage message = new UsageDataMessage(); // Retrieve the User ID using (SQLiteCommand cmd = connection.CreateCommand()) { @@ -185,6 +208,30 @@ namespace ICSharpCode.UsageDataCollector sessions.Select(s => s.SessionID.ToString(CultureInfo.InvariantCulture)).ToArray()); } + #region RemoveUploadedData + /// + /// Removes the data that was successfully uploaded and sets the 'lastUpload' property. + /// + void RemoveUploadedData(IEnumerable sessions) + { + string commaSeparatedSessionIDList = GetCommaSeparatedIDList(sessions); + using (SQLiteConnection connection = OpenConnection()) { + using (SQLiteTransaction transaction = connection.BeginTransaction()) { + using (SQLiteCommand cmd = connection.CreateCommand()) { + cmd.CommandText = @"DELETE FROM Sessions WHERE id IN (" + commaSeparatedSessionIDList + @"); + DELETE FROM Environment WHERE session IN (" + commaSeparatedSessionIDList + @"); + DELETE FROM FeatureUses WHERE session IN (" + commaSeparatedSessionIDList + @"); + DELETE FROM Exceptions WHERE session IN (" + commaSeparatedSessionIDList + @"); + INSERT OR REPLACE INTO Properties (name, value) VALUES ('lastUpload', datetime('now')); + "; + cmd.ExecuteNonQuery(); + } + transaction.Commit(); + } + } + } + #endregion + /// /// Helps keep the memory usage during data preparation down (there are lots of duplicate strings, and we don't /// want to keep them in RAM repeatedly).