SqliteProviderInfoRepository.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. using MediaBrowser.Common.Configuration;
  2. using MediaBrowser.Controller.Providers;
  3. using MediaBrowser.Model.Logging;
  4. using System;
  5. using System.Data;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. namespace MediaBrowser.Server.Implementations.Persistence
  12. {
  13. public class SqliteProviderInfoRepository : BaseSqliteRepository, IProviderRepository
  14. {
  15. private IDbConnection _connection;
  16. private IDbCommand _saveStatusCommand;
  17. private readonly IApplicationPaths _appPaths;
  18. public SqliteProviderInfoRepository(ILogManager logManager, IApplicationPaths appPaths) : base(logManager)
  19. {
  20. _appPaths = appPaths;
  21. }
  22. /// <summary>
  23. /// Gets the name of the repository
  24. /// </summary>
  25. /// <value>The name.</value>
  26. public string Name
  27. {
  28. get
  29. {
  30. return "SQLite";
  31. }
  32. }
  33. /// <summary>
  34. /// Opens the connection to the database
  35. /// </summary>
  36. /// <returns>Task.</returns>
  37. public async Task Initialize()
  38. {
  39. var dbFile = Path.Combine(_appPaths.DataPath, "refreshinfo.db");
  40. _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
  41. string[] queries = {
  42. "create table if not exists MetadataStatus (ItemId GUID PRIMARY KEY, ItemName TEXT, ItemType TEXT, SeriesName TEXT, DateLastMetadataRefresh datetime, DateLastImagesRefresh datetime, ItemDateModified DateTimeNull)",
  43. "create index if not exists idx_MetadataStatus on MetadataStatus(ItemId)",
  44. //pragmas
  45. "pragma temp_store = memory",
  46. "pragma shrink_memory"
  47. };
  48. _connection.RunQueries(queries, Logger);
  49. AddItemDateModifiedCommand();
  50. PrepareStatements();
  51. }
  52. private static readonly string[] StatusColumns =
  53. {
  54. "ItemId",
  55. "ItemName",
  56. "ItemType",
  57. "SeriesName",
  58. "DateLastMetadataRefresh",
  59. "DateLastImagesRefresh",
  60. "ItemDateModified"
  61. };
  62. private void AddItemDateModifiedCommand()
  63. {
  64. using (var cmd = _connection.CreateCommand())
  65. {
  66. cmd.CommandText = "PRAGMA table_info(MetadataStatus)";
  67. using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
  68. {
  69. while (reader.Read())
  70. {
  71. if (!reader.IsDBNull(1))
  72. {
  73. var name = reader.GetString(1);
  74. if (string.Equals(name, "ItemDateModified", StringComparison.OrdinalIgnoreCase))
  75. {
  76. return;
  77. }
  78. }
  79. }
  80. }
  81. }
  82. var builder = new StringBuilder();
  83. builder.AppendLine("alter table MetadataStatus");
  84. builder.AppendLine("add column ItemDateModified DateTime NULL");
  85. _connection.RunQueries(new[] { builder.ToString() }, Logger);
  86. }
  87. /// <summary>
  88. /// Prepares the statements.
  89. /// </summary>
  90. private void PrepareStatements()
  91. {
  92. _saveStatusCommand = _connection.CreateCommand();
  93. _saveStatusCommand.CommandText = string.Format("replace into MetadataStatus ({0}) values ({1})",
  94. string.Join(",", StatusColumns),
  95. string.Join(",", StatusColumns.Select(i => "@" + i).ToArray()));
  96. foreach (var col in StatusColumns)
  97. {
  98. _saveStatusCommand.Parameters.Add(_saveStatusCommand, "@" + col);
  99. }
  100. }
  101. public MetadataStatus GetMetadataStatus(Guid itemId)
  102. {
  103. if (itemId == Guid.Empty)
  104. {
  105. throw new ArgumentNullException("itemId");
  106. }
  107. using (var cmd = _connection.CreateCommand())
  108. {
  109. var cmdText = "select " + string.Join(",", StatusColumns) + " from MetadataStatus where";
  110. cmdText += " ItemId=@ItemId";
  111. cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = itemId;
  112. cmd.CommandText = cmdText;
  113. using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
  114. {
  115. while (reader.Read())
  116. {
  117. return GetStatus(reader);
  118. }
  119. return null;
  120. }
  121. }
  122. }
  123. private MetadataStatus GetStatus(IDataReader reader)
  124. {
  125. var result = new MetadataStatus
  126. {
  127. ItemId = reader.GetGuid(0)
  128. };
  129. if (!reader.IsDBNull(1))
  130. {
  131. result.ItemName = reader.GetString(1);
  132. }
  133. if (!reader.IsDBNull(2))
  134. {
  135. result.ItemName = reader.GetString(2);
  136. }
  137. if (!reader.IsDBNull(3))
  138. {
  139. result.SeriesName = reader.GetString(3);
  140. }
  141. if (!reader.IsDBNull(4))
  142. {
  143. result.DateLastMetadataRefresh = reader.GetDateTime(4).ToUniversalTime();
  144. }
  145. if (!reader.IsDBNull(5))
  146. {
  147. result.DateLastImagesRefresh = reader.GetDateTime(5).ToUniversalTime();
  148. }
  149. if (!reader.IsDBNull(6))
  150. {
  151. result.ItemDateModified = reader.GetDateTime(6).ToUniversalTime();
  152. }
  153. return result;
  154. }
  155. public async Task SaveMetadataStatus(MetadataStatus status, CancellationToken cancellationToken)
  156. {
  157. if (status == null)
  158. {
  159. throw new ArgumentNullException("status");
  160. }
  161. cancellationToken.ThrowIfCancellationRequested();
  162. await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false);
  163. IDbTransaction transaction = null;
  164. try
  165. {
  166. transaction = _connection.BeginTransaction();
  167. _saveStatusCommand.GetParameter(0).Value = status.ItemId;
  168. _saveStatusCommand.GetParameter(1).Value = status.ItemName;
  169. _saveStatusCommand.GetParameter(2).Value = status.ItemType;
  170. _saveStatusCommand.GetParameter(3).Value = status.SeriesName;
  171. _saveStatusCommand.GetParameter(4).Value = status.DateLastMetadataRefresh;
  172. _saveStatusCommand.GetParameter(5).Value = status.DateLastImagesRefresh;
  173. _saveStatusCommand.GetParameter(6).Value = status.ItemDateModified;
  174. _saveStatusCommand.Transaction = transaction;
  175. _saveStatusCommand.ExecuteNonQuery();
  176. transaction.Commit();
  177. }
  178. catch (OperationCanceledException)
  179. {
  180. if (transaction != null)
  181. {
  182. transaction.Rollback();
  183. }
  184. throw;
  185. }
  186. catch (Exception e)
  187. {
  188. Logger.ErrorException("Failed to save provider info:", e);
  189. if (transaction != null)
  190. {
  191. transaction.Rollback();
  192. }
  193. throw;
  194. }
  195. finally
  196. {
  197. if (transaction != null)
  198. {
  199. transaction.Dispose();
  200. }
  201. WriteLock.Release();
  202. }
  203. }
  204. protected override void CloseConnection()
  205. {
  206. if (_connection != null)
  207. {
  208. if (_connection.IsOpen())
  209. {
  210. _connection.Close();
  211. }
  212. _connection.Dispose();
  213. _connection = null;
  214. }
  215. }
  216. }
  217. }