aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2014-08-10 18:13:17 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2014-08-10 18:13:17 -0400
commite84ba17b9f48a3bc8811b1a89c54c25bc6607599 (patch)
tree220ce22658497f75f4d575296fc903cd19a60339 /MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs
parent0f508dab47ebcc27d973840d03025f28f52a14b6 (diff)
add activity log feature
Diffstat (limited to 'MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs')
-rw-r--r--MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs293
1 files changed, 293 insertions, 0 deletions
diff --git a/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs b/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs
new file mode 100644
index 000000000..787cbcc5b
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs
@@ -0,0 +1,293 @@
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Activity;
+using MediaBrowser.Model.Activity;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Querying;
+using MediaBrowser.Server.Implementations.Persistence;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Globalization;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Activity
+{
+ public class ActivityRepository : IActivityRepository, IDisposable
+ {
+ private IDbConnection _connection;
+ private readonly ILogger _logger;
+ private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1);
+ private readonly IServerApplicationPaths _appPaths;
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
+ private IDbCommand _saveActivityCommand;
+
+ public ActivityRepository(ILogger logger, IServerApplicationPaths appPaths)
+ {
+ _logger = logger;
+ _appPaths = appPaths;
+ }
+
+ public async Task Initialize()
+ {
+ var dbFile = Path.Combine(_appPaths.DataPath, "activitylog.db");
+
+ _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
+
+ string[] queries = {
+
+ "create table if not exists ActivityLogEntries (Id GUID PRIMARY KEY, Name TEXT, Overview TEXT, ShortOverview TEXT, Type TEXT, ItemId TEXT, UserId TEXT, DateCreated DATETIME, LogSeverity TEXT)",
+ "create index if not exists idx_ActivityLogEntries on ActivityLogEntries(Id)",
+
+ //pragmas
+ "pragma temp_store = memory",
+
+ "pragma shrink_memory"
+ };
+
+ _connection.RunQueries(queries, _logger);
+
+ PrepareStatements();
+ }
+
+ private void PrepareStatements()
+ {
+ _saveActivityCommand = _connection.CreateCommand();
+ _saveActivityCommand.CommandText = "replace into ActivityLogEntries (Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity) values (@Id, @Name, @Overview, @ShortOverview, @Type, @ItemId, @UserId, @DateCreated, @LogSeverity)";
+
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@Id");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@Name");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@Overview");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@ShortOverview");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@Type");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@ItemId");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@UserId");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@DateCreated");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@LogSeverity");
+ }
+
+ private const string BaseActivitySelectText = "select Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity from ActivityLogEntries";
+
+ public Task Create(ActivityLogEntry entry)
+ {
+ return Update(entry);
+ }
+
+ public async Task Update(ActivityLogEntry entry)
+ {
+ if (entry == null)
+ {
+ throw new ArgumentNullException("entry");
+ }
+
+ await _writeLock.WaitAsync().ConfigureAwait(false);
+
+ IDbTransaction transaction = null;
+
+ try
+ {
+ transaction = _connection.BeginTransaction();
+
+ var index = 0;
+
+ _saveActivityCommand.GetParameter(index++).Value = new Guid(entry.Id);
+ _saveActivityCommand.GetParameter(index++).Value = entry.Name;
+ _saveActivityCommand.GetParameter(index++).Value = entry.Overview;
+ _saveActivityCommand.GetParameter(index++).Value = entry.ShortOverview;
+ _saveActivityCommand.GetParameter(index++).Value = entry.Type;
+ _saveActivityCommand.GetParameter(index++).Value = entry.ItemId;
+ _saveActivityCommand.GetParameter(index++).Value = entry.UserId;
+ _saveActivityCommand.GetParameter(index++).Value = entry.Date;
+ _saveActivityCommand.GetParameter(index++).Value = entry.Severity.ToString();
+
+ _saveActivityCommand.Transaction = transaction;
+
+ _saveActivityCommand.ExecuteNonQuery();
+
+ transaction.Commit();
+ }
+ catch (OperationCanceledException)
+ {
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ catch (Exception e)
+ {
+ _logger.ErrorException("Failed to save record:", e);
+
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ finally
+ {
+ if (transaction != null)
+ {
+ transaction.Dispose();
+ }
+
+ _writeLock.Release();
+ }
+ }
+
+ public QueryResult<ActivityLogEntry> GetActivityLogEntries(int? startIndex, int? limit)
+ {
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = BaseActivitySelectText;
+
+ var whereClauses = new List<string>();
+
+ if (startIndex.HasValue && startIndex.Value > 0)
+ {
+ whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM ActivityLogEntries ORDER BY DateCreated DESC LIMIT {0})",
+ startIndex.Value.ToString(_usCulture)));
+ }
+
+ if (whereClauses.Count > 0)
+ {
+ cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray());
+ }
+
+ cmd.CommandText += " ORDER BY DateCreated DESC";
+
+ if (limit.HasValue)
+ {
+ cmd.CommandText += " LIMIT " + limit.Value.ToString(_usCulture);
+ }
+
+ cmd.CommandText += "; select count (Id) from ActivityLogEntries";
+
+ var list = new List<ActivityLogEntry>();
+ var count = 0;
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
+ {
+ while (reader.Read())
+ {
+ list.Add(GetEntry(reader));
+ }
+
+ if (reader.NextResult() && reader.Read())
+ {
+ count = reader.GetInt32(0);
+ }
+ }
+
+ return new QueryResult<ActivityLogEntry>()
+ {
+ Items = list.ToArray(),
+ TotalRecordCount = count
+ };
+ }
+ }
+
+ private ActivityLogEntry GetEntry(IDataReader reader)
+ {
+ var index = 0;
+
+ var info = new ActivityLogEntry
+ {
+ Id = reader.GetGuid(index).ToString("N")
+ };
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.Name = reader.GetString(index);
+ }
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.Overview = reader.GetString(index);
+ }
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.ShortOverview = reader.GetString(index);
+ }
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.Type = reader.GetString(index);
+ }
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.ItemId = reader.GetString(index);
+ }
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.UserId = reader.GetString(index);
+ }
+
+ index++;
+ info.Date = reader.GetDateTime(index).ToUniversalTime();
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.Severity = (LogSeverity)Enum.Parse(typeof(LogSeverity), reader.GetString(index), true);
+ }
+
+ return info;
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ private readonly object _disposeLock = new object();
+
+ /// <summary>
+ /// Releases unmanaged and - optionally - managed resources.
+ /// </summary>
+ /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+ protected virtual void Dispose(bool dispose)
+ {
+ if (dispose)
+ {
+ try
+ {
+ lock (_disposeLock)
+ {
+ if (_connection != null)
+ {
+ if (_connection.IsOpen())
+ {
+ _connection.Close();
+ }
+
+ _connection.Dispose();
+ _connection = null;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error disposing database", ex);
+ }
+ }
+ }
+ }
+}